Zulip Chat Archive
Stream: maths
Topic: dinatural transformations
Scott Morrison (Oct 01 2021 at 22:07):
@fosco, you may want to start here:
import category_theory.products.basic
open opposite
namespace category_theory
variables {C D : Type*} [category C] [category D]
structure dinat_trans (F G : Cᵒᵖ × C ⥤ D) :=
(app := Π X, F.obj (op X, X) ⟶ G.obj (op X, X))
/- ... axioms ... -/
end category_theory
fosco (Oct 01 2021 at 22:31):
ok, a very basic question.
structure dinat_trans (F G : Cᵒᵖ × C ⥤ D) :=
(app := Π X, F.obj (op X, X) ⟶ G.obj (op X, X))
(dinaturality : ∀ ⦃X Y : C⦄ (f : X ⟶ Y),
F.map (op f, 𝟙 X) ≫ app X ≫ G.map (op 𝟙 X, f) = F.map (op 𝟙 Y,f) ≫ app Y ≫ G (op f, 𝟙 Y) . obviously)
this gives me an error,
prod.mk (op f)
term
op f
has type
(X ⟶ Y)ᵒᵖ
but is expected to have type
?m_1.fst ⟶ ?m_2.fst
and this is telling me that I'm not building the morphism in C^op x C correctly. What is the correct syntax to refer to the morphism in ?
fosco (Oct 01 2021 at 22:32):
(PS: it's night time for me in my timezone ;-) I'll get back at it tomorrow)
Reid Barton (Oct 01 2021 at 22:33):
For a morphism, it should be f.op
, I think.
fosco (Oct 01 2021 at 22:34):
Same error if I change to f.op
Reid Barton (Oct 01 2021 at 22:34):
Exactly the same?
Reid Barton (Oct 01 2021 at 22:35):
Well, there is a second op f
fosco (Oct 01 2021 at 22:35):
type mismatch at application
prod.mk f.op
term
f.op
has type
op Y ⟶ op X
but is expected to have type
?m_1.fst ⟶ ?m_2.fst
where is ?m_1
implicitly defined?
Reid Barton (Oct 01 2021 at 22:36):
Aha I didn't read the whole error message. It is closer now, though!
fosco (Oct 01 2021 at 22:36):
Same error message, but less mistake :grinning:
Reid Barton (Oct 01 2021 at 22:37):
For these metavariables like ?m_1
(as far as I know) you just have to guess, so here probably it is the implicit source object argument of F.map
fosco (Oct 01 2021 at 22:38):
is at least (f,g)
the right way to define a morphism in a product category? Initially I thought I had to use angle brackets..
Reid Barton (Oct 01 2021 at 22:38):
That is, I'm not sure if Lean is smart enough here to guess what objects (f.op, 𝟙 X)
is meant to be a map between... you can tell it explicitly, but it's a bit inconvenient
fosco (Oct 01 2021 at 22:40):
how do you tell it explicitly?
Reid Barton (Oct 01 2021 at 22:41):
Something like (f.op, 𝟙 X) : (op Y, X) ⟶ (op X, X)
(if I got it right)
Reid Barton (Oct 01 2021 at 22:41):
I'm not sure it will help, but it might
fosco (Oct 01 2021 at 22:43):
And where should I specify this typing?
fosco (Oct 01 2021 at 22:43):
I thought given the type of f
there's a unique way to infer the type of (f.op, 1 X)
...
Reid Barton (Oct 01 2021 at 22:45):
It has a unique type in the sense that its type is known to be prod blah blah
but in principle there could be various pairs of objects of Cᵒᵖ × C
between which the type of maps is that specific type... which is a bit annoying.
Reid Barton (Oct 01 2021 at 22:45):
F.map ((f.op, 𝟙 X) : (op Y, X) ⟶ (op X, X))
Reid Barton (Oct 01 2021 at 22:46):
Based on src#category_theory.bifunctor.diagonal it seems like this is what you're meant to write
Reid Barton (Oct 01 2021 at 22:46):
Probably there should be something like F.map_prod f g
to make this easier.
Reid Barton (Oct 01 2021 at 22:48):
I see the file I linked above is from 2017 so maybe it already exists... but I looked there because it seemed like the logical place for it
fosco (Oct 01 2021 at 22:49):
open opposite
namespace category_theory
variables {C D : Type*} [category C] [category D]
structure dinat_trans (F G : Cᵒᵖ × C ⥤ D) :=
(app : Π X, F.obj (op X, X) ⟶ G.obj (op X, X))
(dinaturality : ∀ ⦃X Y : C⦄ (f : X ⟶ Y),
F.map ((f.op, 𝟙 X) : (op Y, X) ⟶ (op X, X)) ≫ app X ≫ G.map (((𝟙 X).op, f) : (op X,X) ⟶ (op X,Y)) = F.map (((𝟙 Y).op, f) : (op Y,X) ⟶ (op Y,Y)) ≫ app Y ≫ G.map (f.op, 𝟙 Y) . obviously)
end category_theory
no errors!
fosco (Oct 01 2021 at 22:50):
:smile: tomorrow, co/wedges!
Scott Morrison (Oct 01 2021 at 22:52):
Make sure in a ```
block that you start with a new line. Otherwise zulip swallows the first line and tries to interpret it as a language instruction for the code block.
Scott Morrison (Oct 01 2021 at 22:55):
This is slightly terser:
import category_theory.products.basic
open opposite
namespace category_theory
variables {C D E : Type*} [category C] [category D] [category E]
-- TODO move to category_theory.products.bifunctor, and make use of there
/-- A synonym for `F.map (f, g)`, helpful because Lean struggles to typecheck `(f, g)`. -/
def functor.map_prod (F : C × D ⥤ E) {W X : C} {Y Z : D} (f : W ⟶ X) (g : Y ⟶ Z) :
F.obj (W, Y) ⟶ F.obj (X, Z) :=
F.map (f, g)
structure dinat_trans (F G : Cᵒᵖ × C ⥤ D) :=
(app : Π X, F.obj (op X, X) ⟶ G.obj (op X, X))
(dinaturality : ∀ ⦃X Y : C⦄ (f : X ⟶ Y),
F.map_prod f.op (𝟙 _) ≫ app X ≫ G.map_prod (𝟙 _) f =
F.map_prod (𝟙 _) f ≫ app Y ≫ G.map_prod f.op (𝟙 _) . obviously)
end category_theory
using Reid's map_prod
suggestion.
Scott Morrison (Oct 01 2021 at 22:55):
Note also that by writing (𝟙 _)
I can avoid having to write (𝟙 X).op
.
Scott Morrison (Oct 01 2021 at 22:57):
(Note also Lean's style guide says no indenting for structure fields, and no long lines. :-)
fosco (Oct 02 2021 at 08:28):
def constant_functor (X : D) : C ⥤ D :=
{ obj := λ Y, X,
map := λ Y Y' f, 𝟙 X, }
def promote_covariant (F : C ⥤ D) : (Cᵒᵖ × C ⥤ D) :=
{ obj := λ Z, F.obj Z.snd,
map := λ Z W f, F.map f.snd, }
def promote_contravariant (F : Cᵒᵖ ⥤ D) : (Cᵒᵖ × C ⥤ D) :=
{ obj := λ Z, F.obj Z.fst,
map := λ Z W f, F.map f.fst, }
def wedge (F : Cᵒᵖ × C ⥤ D) (X : D) : dinat_trans (promote_covariant (constant_functor X)) F := sorry
def cowedge (F : Cᵒᵖ × C ⥤ D) (X : D) : dinat_trans F (promote_covariant (constant_functor X)) := sorry
a few other definitions; I'm not sure wedge
and cowedge
are definitions though: they are _functions_ eating a functor and an object of , and giving back the category of dinatural transformations between the two. So, is a type! I'm not sure this is the best design choice.
Johan Commelin (Oct 02 2021 at 08:33):
I hope that functor.const
exists already.
Johan Commelin (Oct 02 2021 at 08:35):
And promote_covariant
should be something like functor.snd ⋙ F
fosco (Oct 02 2021 at 08:35):
Sure. I am just trying to reinvent the wheel to get a grip on the basic defs
(I should also have a look at cone
and cocone
...)
fosco (Oct 02 2021 at 08:38):
Johan Commelin said:
And
promote_covariant
should be something likefunctor.snd ⋙ F
unknown identifier 'category_theory.functor.snd'
Johan Commelin (Oct 02 2021 at 08:39):
Ooh, it's probably just It is category_theory.snd
, sorry.category_theory.prod.snd
Johan Commelin (Oct 02 2021 at 08:39):
Johan Commelin (Oct 02 2021 at 08:39):
Voila :this:
fosco (Oct 02 2021 at 08:41):
Now I see a complaint for \ggg
type mismatch at application
functor.comp prod.snd
term
prod.snd
has type
Π (C : Type ?) [_inst_1 : category C] (D : Type ?) [_inst_2 : category D], C × D ⥤ D : Type (max
(?+1)
(max ? (?+1))
(?+1)
(max ? (?+1))
(max ? ?)
?
?
?)
but is expected to have type
Cᵒᵖ × C ⥤ ?m_1 : Type (max u_4 ? u_1 ?)
Johan Commelin (Oct 02 2021 at 08:46):
Aah, prod.snd
takes to arguments (namely the factors)
Johan Commelin (Oct 02 2021 at 08:46):
So prod.snd _ _ ⋙ F
should work
fosco (Oct 02 2021 at 08:46):
perfect
Johan Commelin (Oct 02 2021 at 08:46):
Sorry, I should have tested my code before commenting
fosco (Oct 02 2021 at 08:47):
Nah, it's me, I should start from the beginning, be more systematic. Instead I am learning the syntax along the way.
Johan Commelin (Oct 02 2021 at 08:48):
It's a lot more fun that way. I also jumped straight in (-;
Scott Morrison (Oct 02 2021 at 10:11):
@fosco, I think your definition of wedge
is on the wrong track. You don't want D
as a parameter, but rather as a field of the wedge
.
Scott Morrison (Oct 02 2021 at 10:13):
You could write
def wedge (F : Cᵒᵖ × C ⥤ D) := \Sigma X : D, dinat_trans ... F := sorry
but better would be
structure wedge (F : Cᵒᵖ × C ⥤ D) :=
(X : D)
(\a : dinat_trans ... F)
and then instance (F) : category (wedge F) := ...
Scott Morrison (Oct 02 2021 at 10:16):
(Probably before the instance
you want to enter the wedge
namespace and define hom
, presumably as another structure.)
fosco (Oct 02 2021 at 10:37):
I agree; also, promote
s are redundant, lean figures out alone that the domain of the constant functor must be .
fosco (Oct 02 2021 at 10:41):
What is hom
?
In fact, I would like to define the twisted arrow category of :
- objects : the morphisms of
- morphisms : the pairs such that the obvious square commutes
is this a structure
that then I have to prove is a category?
Again, I am discovering the syntax along the way :smile: be patient...
fosco (Oct 02 2021 at 10:42):
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) := sorry
this seems to work (it only complains for the sorry
)
fosco (Oct 02 2021 at 10:47):
Now I would love to have something similar to agda's ctrl-R
to auto-generate the fields I have to fill (hom, id, comp)... wishful thinking?
Ruben Van de Velde (Oct 02 2021 at 10:48):
Replace the sorry by an underscore, and if you're in vs code, a lightbulb should show up
Johan Commelin (Oct 02 2021 at 10:52):
Ctrl
-.
will open the lightbulb menu. Then hit <Up>
-<Up>
-<Enter>
and you will have your skeleton :laughing:
fosco (Oct 02 2021 at 10:53):
I know very little as you can see! :smile:
fosco (Oct 02 2021 at 10:58):
structure wedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans (constant_functor tip) F)
structure cowedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans F (constant_functor tip))
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) :=
{ hom := λ U V, U.tip ⟶ V.tip,
id := λ X, eq_to_hom rfl,
comp := λ X Y Z f g, f ≫ g, }
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, U.tip ⟶ V.tip,
id := λ X, eq_to_hom rfl,
comp := λ X Y Z f g, f ≫ g, }
fosco (Oct 02 2021 at 11:03):
Now for the twisted arrow category...
fosco (Oct 02 2021 at 11:16):
Hmmm, I am having a hard time again, figuring out how to define it
fosco (Oct 02 2021 at 11:20):
instance twisted : category (C.hom) :=
{ hom := _,
id := _,
comp := _,
id_comp' := _,
comp_id' := _,
assoc' := _ }
I would like to say: if is a category, there is a category having objects the class of morphisms of , and morphisms the pairs (u,v)
as above; I have two problems: first, I can't figure out where to put the information that the class of objects of is ; second, I want just some pairs of morphisms (u,v): how does one consider just some pairs (u,v), subject to a certain condition?
Scott Morrison (Oct 02 2021 at 11:25):
Before you go too far: please use the existing functor.const
, rather than rolling your own.
Scott Morrison (Oct 02 2021 at 11:26):
In wedge
, I'd suggest for now calling tip
instead X
. It's not great, but it will be consistent with the terminology for cone
and cocone
. If you feel strongly about it, we can make a PR to update cone
and cocone
later. :-)
Scott Morrison (Oct 02 2021 at 11:27):
I'm confused. Your category instances for wedge
and cowedge
are wrong. The morphisms aren't just morphisms between the tips, but morphisms satisfying some condition.
Scott Morrison (Oct 02 2021 at 11:27):
This is why you need to create a structure wedge.hom := ...
Scott Morrison (Oct 02 2021 at 11:27):
Which will carry the morphism and this condition. See how this is implemented for comma
or cone
.
fosco (Oct 02 2021 at 11:29):
Scott Morrison said:
Before you go too far: please use the existing
functor.const
, rather than rolling your own.
Replacing constant_functor
with functor.const
doesn't work...
Scott Morrison (Oct 02 2021 at 11:29):
Let's see: src#functor.const.
Scott Morrison (Oct 02 2021 at 11:30):
Nope, that's wrong.
fosco (Oct 02 2021 at 11:30):
Scott Morrison said:
I'm confused. Your category instances for
wedge
andcowedge
are wrong. The morphisms aren't just morphisms between the tips, but morphisms satisfying some condition.
Indeed: because I don't know how to specify a condition that the morphisms have to satisfy. I'll look into cone
Scott Morrison (Oct 02 2021 at 11:30):
src#category_theory.functor.const
fosco (Oct 02 2021 at 11:30):
type mismatch at application
functor.const tip
term
tip
has type
D : Type u_2
but is expected to have type
Type ? : Type (?+1)
Scott Morrison (Oct 02 2021 at 11:31):
There's functor.const
for you. You'll have to import category_theory.const
to get it. Note that it is set up to be functorial, so you'll need to see how it is used.
Scott Morrison (Oct 02 2021 at 11:31):
Read the module doc-string in the link I just gave you to see how to use functor.const
.
Scott Morrison (Oct 02 2021 at 11:32):
(Later you will be happy that functor.const
is functorial in the constant. :-)
Scott Morrison (Oct 02 2021 at 11:32):
(The doc-string for functor.const
could be more helpful, I see. At least the module doc-string explains it.)
fosco (Oct 02 2021 at 11:33):
it seems to me that this should work
structure wedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans (functor.const tip) F)
but it doesn't
Scott Morrison (Oct 02 2021 at 11:35):
As I've been saying in the message above, functor.const
takes more arguments than you are giving it.
Scott Morrison (Oct 02 2021 at 11:35):
(Because it is set up to be functorial.)
Scott Morrison (Oct 02 2021 at 11:35):
To see how to set up wedge.hom
you should look at src#category_theory.limits.cone_morphism.
Scott Morrison (Oct 02 2021 at 11:37):
You probably just need (functor.const _).obj tip
Scott Morrison (Oct 02 2021 at 11:37):
(And if you write open functor
higher up in your file you can just write const
, rather than functor.const
.
Scott Morrison (Oct 02 2021 at 11:39):
Error messages of the form
type mismatch at application
functor.const tip
has type
D : Type u_2
but is expected to have type
Type ? : Type (?+1)
are super useful, and worth learning how to interpret. It's saying that that first argument of functor.const
is not an object of a category, but actually a type.
Scott Morrison (Oct 02 2021 at 11:39):
It is expecting to be given the name of the "source category" for the constant functor that you want.
Scott Morrison (Oct 02 2021 at 11:40):
Notice in your earlier constant_functor
the source category was an "implicit" argument (i.e. given via curly braces { }). This means you can leave them out, but Lean has to be able to guess the correct value from context. That's not always a good idea, so the mathlib version functor.const
has to be told the source category "explicitly".
fosco (Oct 02 2021 at 11:41):
so, const (domain) (object)
?
Scott Morrison (Oct 02 2021 at 11:41):
The next difference is that functor.const C
doesn't just take an object of D
and spit out a functor C \func D
. It is actually giving you a functor from C
to C \func D
.
Scott Morrison (Oct 02 2021 at 11:41):
Hence we have to write (const domain).obj object
to apply it to an object.
Scott Morrison (Oct 02 2021 at 11:42):
(You could write (const domain).map morphism
to apply it to a morphism (obtaining, of course, the identity morphism on your chosen constant.)
Scott Morrison (Oct 02 2021 at 11:43):
Eventually you need all these functoriality statements (even if automation takes care of plugging them in at the right places), so we tend to package them all up at the beginning, rather than thinking of them as separate constructions.
fosco (Oct 02 2021 at 11:47):
I'm starting to understand, but I am still confused
- How can I possibly know how many arguments, and in what order, are needed by
const
, looking at its type here?
def const : C ⥤ (J ⥤ C) :=
{ obj := λ X,
{ obj := λ j, X,
map := λ j j' f, 𝟙 X },
map := λ X Y f, { app := λ j, f } }
- I understand that this
const
gives a functor fromC
toC \func D
, which is different from what I defined. Yet,const (Cᵒᵖ × C) tip
gives the same type mismatch.
Scott Morrison (Oct 02 2021 at 11:47):
Note that functors are not functions!
Scott Morrison (Oct 02 2021 at 11:48):
If F : C ⥤ D
, and X : C
, you can't just write F X
.
Scott Morrison (Oct 02 2021 at 11:48):
You need to write F.obj X
.
Scott Morrison (Oct 02 2021 at 11:48):
So you need to write (const (Cᵒᵖ × C)).obj tip
fosco (Oct 02 2021 at 11:49):
Scott Morrison said:
So you need to write
(const (Cᵒᵖ × C)).obj tip
Doesn't work! I tried.
Scott Morrison (Oct 02 2021 at 11:49):
Show me the error message?
fosco (Oct 02 2021 at 11:49):
invalid field notation, type is not of the form (C ...) where C is a constant
const (Cᵒᵖ × C)
has type
Type ? → Type u_1
Scott Morrison (Oct 02 2021 at 11:49):
Might need to post the #mwe.
fosco (Oct 02 2021 at 11:49):
structure wedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans ((const (Cᵒᵖ × C)).obj tip) F)
Scott Morrison (Oct 02 2021 at 11:49):
Are you sure this const
is category_theory.functor.const
?
Scott Morrison (Oct 02 2021 at 11:50):
(i.e. if you right-click on it and go-to-definition you land in the right place)
Scott Morrison (Oct 02 2021 at 11:50):
It's possible you're seeing some other const
, because I don't think it should have type Type ? → Type u_1
.
Scott Morrison (Oct 02 2021 at 11:51):
Maybe you can post your whole file?
Scott Morrison (Oct 02 2021 at 11:53):
Sorry to derail you by suggesting using functor.const
instead of your own. In the long run it will pay off but I appreciate it is annoying now. :-)
fosco (Oct 02 2021 at 11:54):
Now it works, if I write functor.const
; for some reason open
ing functor
at the beginning doesn't work
fosco (Oct 02 2021 at 11:54):
Here's the whole file anyway
import category_theory.products.basic
import category_theory.const
open opposite
open functor
namespace category_theory
variables {C D E : Type*} [category C] [category D] [category E]
def functor.map_prod (F : C × D ⥤ E) {W X : C} {Y Z : D} (f : W ⟶ X) (g : Y ⟶ Z) :
F.obj (W, Y) ⟶ F.obj (X, Z) :=
F.map (f, g)
structure dinat_trans (F G : Cᵒᵖ × C ⥤ D) :=
(app : Π X, F.obj (op X, X) ⟶ G.obj (op X, X))
(dinaturality : ∀ ⦃X Y : C⦄ (f : X ⟶ Y),
F.map_prod f.op (𝟙 _) ≫ app X ≫ G.map_prod (𝟙 _) f =
F.map_prod (𝟙 _) f ≫ app Y ≫ G.map_prod f.op (𝟙 _) . obviously)
namespace wedge
structure wedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans ((functor.const (Cᵒᵖ × C)).obj tip) F)
structure cowedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans F ((functor.const (Cᵒᵖ × C)).obj tip))
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) :=
{ hom := λ U V, U.tip ⟶ V.tip,
id := λ X, eq_to_hom rfl,
comp := λ X Y Z f g, f ≫ g, }
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, U.tip ⟶ V.tip,
id := λ X, eq_to_hom rfl,
comp := λ X Y Z f g, f ≫ g, }
-- instance twisted : category (hom C) :=
-- { hom := _,
-- id := _,
-- comp := _,
-- id_comp' := _,
-- comp_id' := _,
-- assoc' := _ }
end wedge
end category_theory
Scott Morrison (Oct 02 2021 at 11:55):
Ah --- did you open functor
inside or outside the namespace category_theory
?
fosco (Oct 02 2021 at 11:55):
outside
Scott Morrison (Oct 02 2021 at 11:55):
The problem is that the Haskell programmers put functor
in the root namespace, to mean a type level functor like programmers like.
Scott Morrison (Oct 02 2021 at 11:56):
And the real functor
is only in the category_theory
namespace.
Scott Morrison (Oct 02 2021 at 11:56):
So you accidentally picked up the other one.
fosco (Oct 02 2021 at 11:56):
Scott Morrison said:
The problem is that the Haskell programmers put
functor
in the root namespace, to mean a type level functor like programmers like.
It's always haskellers' fault :grinning:
Scott Morrison (Oct 02 2021 at 11:56):
I've been wanting to trying move the programmers' functor
into a namespace, as control.functor
.
Scott Morrison (Oct 02 2021 at 11:56):
But never did it.
Scott Morrison (Oct 02 2021 at 11:57):
Maybe I'll go investigate that again.
fosco (Oct 02 2021 at 11:57):
yet the same thing happens if I move the open functor
inside the category_theory
namespace
Scott Morrison (Oct 02 2021 at 11:57):
In any case, if you move the open
inside, or write open category_theory.functor
, you should be good.
fosco (Oct 02 2021 at 11:58):
yes, open category_theory.functor
works.
fosco (Oct 02 2021 at 11:58):
Whew!
Scott Morrison (Oct 02 2021 at 12:01):
Next up:
get rid of your instance : category (wedge ...)
, and instead first define structure wedge.hom (...) := ...
Kevin Buzzard (Oct 02 2021 at 12:06):
By the way one answer to "how do I figure out what inputs are implicit and what are explicit" is "just hover over the function definition and its type will pop up" and another is #check @const
Scott Morrison (Oct 02 2021 at 12:07):
The complication here was that it wasn't either explicit or implicit: it was functorial.
Scott Morrison (Oct 02 2021 at 12:08):
Okay, well I'm off for now @fosco. Good luck. Reading some examples like arrow categories, comma categories, and categories of cones will be helpful for what you are doing next.
fosco (Oct 02 2021 at 12:09):
Thanks for your help!
fosco (Oct 02 2021 at 12:12):
This should be nearer to what you were suggesting:
structure wedge_morphism (U V : wedge T) :=
(hom : U.tip ⟶ V.tip)
(w' : ∀ j : C, hom ≫ V.α.app j = U.α.app j . obviously)
structure cowedge_morphism (U V : cowedge T) :=
(hom : U.tip ⟶ V.tip)
(w' : ∀ j : C, U.α.app j ≫ hom = V.α.app j . obviously)
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) :=
{ hom := λ U V, wedge_morphism U V,
id := λ X, eq_to_hom rfl,
comp := λ X Y Z f g, f ≫ g, }
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, cowedge_morphism U V
id := λ X, eq_to_hom rfl,
comp := λ X Y Z f g, f ≫ g, }
fosco (Oct 02 2021 at 12:13):
(I added [T : Cᵒᵖ × C ⥤ D]
among the variables)
Kevin Buzzard (Oct 02 2021 at 12:13):
Another thing you might want to try @fosco (if you didn't already) is doing Scott's problem sheet in LFTCM2020: clone https://github.com/leanprover-community/lftcm2020 with leanproject get lftcm2020
, open the lftcm2020 folder with VS Code, make your way to src/exercises_sources/thursday/category_theory/
and try filling in the sorry
s. Beforehand you might want to watch the accompanying video.
fosco (Oct 02 2021 at 12:15):
I watched part of Scott's video :smile: it motivated me to enter here.
Kevin Buzzard (Oct 02 2021 at 12:15):
oh nice!
Scott Morrison (Oct 02 2021 at 12:16):
Excellent!
Kevin Buzzard (Oct 02 2021 at 12:16):
I'm glad that people can find their way to that stuff independently of being pointed there from here
Scott Morrison (Oct 02 2021 at 12:17):
Don't forgot to:
restate_axiom wedge_morphism.w' -- this will make a copy called `w`, and clean up some mess `. obviously` leaves
attribute [simp] wedge_morphism.w
Scott Morrison (Oct 02 2021 at 12:17):
It's important as you build new structures that you simultaneously define simp
lemmas which make use of the bundled axioms. If you do this right, you can avoid lots of boring proofs!
fosco (Oct 02 2021 at 12:18):
I feel I need a more systematic approach to understand this kind of subtlety.
Scott Morrison (Oct 02 2021 at 12:19):
Hmm... before we go there. I don't think
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) :=
{ hom := λ U V, wedge_morphism U V,
id := λ X, eq_to_hom rfl,
comp := λ X Y Z f g, f ≫ g, }
can possibly be working.
Scott Morrison (Oct 02 2021 at 12:19):
Because id
and comp
should be constructing new wedge_morphism
s.
Scott Morrison (Oct 02 2021 at 12:20):
After all, you need to check the condition holds for the composition of two wedge morphisms, using the conditions for the two wedge morphisms!
Scott Morrison (Oct 02 2021 at 12:20):
(Or rather, we hope that we don't need to check this, but that Lean will check it for us.)
fosco (Oct 02 2021 at 12:20):
uh, probably they were auto-filled sorry
s; the problem though is earlier
fosco (Oct 02 2021 at 12:20):
in the definition of hom
fosco (Oct 02 2021 at 12:21):
synthesized type class instance is not definitionally equal to expression inferred by typing rules, synthesized
⁇
inferred
F
fosco (Oct 02 2021 at 12:21):
I just copied from the definition of cone_category
Scott Morrison (Oct 02 2021 at 12:22):
Hrmm... we need to sort that out first.
Scott Morrison (Oct 02 2021 at 12:23):
Now, you said above that you introduced T
as a variable, but you put it in square brackets. That was wrong -- square brackets are only for typeclasses.
Scott Morrison (Oct 02 2021 at 12:24):
(A good rule of thumb, by the way, is to always fix the first error in the file first, and to not proceed past errors! sorry
is okay, but an error higher up can really obscure what's going on.)
Scott Morrison (Oct 02 2021 at 12:25):
Changing the square brackets to { }
on T
will give you the correct error message now.
Scott Morrison (Oct 02 2021 at 12:26):
So you want something more like:
variables {T : Cᵒᵖ × C ⥤ D}
structure wedge_morphism (U V : wedge T) :=
(hom : U.tip ⟶ V.tip)
(w' : ∀ j : C, hom ≫ V.α.app j = U.α.app j . obviously)
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) :=
{ hom := λ U V, wedge_morphism U V,
id := λ X, ⟨𝟙 _⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom⟩, }
This still has an error, but notice that in the id
field we didn't need to provide the proof of w'
! Hooray, Lean did it for us.
Scott Morrison (Oct 02 2021 at 12:27):
However in the comp
field Lean complains that it can't prove w'
.
Scott Morrison (Oct 02 2021 at 12:27):
But if you add
restate_axiom wedge_morphism.w'
attribute [simp] wedge_morphism.w
then that error goes away too! Hooray!
Scott Morrison (Oct 02 2021 at 12:28):
But there are still more errors: the id
and comp
fields both typecheck, but there's an error on the {
of the instance
. If you read the messages, you'll see that it's failing to prove the comp_id'
id_comp'
and assoc'
fields of category
.
Scott Morrison (Oct 02 2021 at 12:29):
The reason here is that we haven't explained to Lean how one checks that two wedge_morphism
s are equal: you check that their hom
s are equal!
Scott Morrison (Oct 02 2021 at 12:30):
So we add
@[ext]
lemma wedge_morphis.ext {U V : wedge T} (f g : wedge_morphism U V) (w : f.hom = g.hom) : f = g :=
by { cases f, cases g, tidy, }
Scott Morrison (Oct 02 2021 at 12:31):
The @[ext]
annotation here says: "if automation is trying to prove things are equal by the strategy of proving they are equal "componentwise" in some sense, try using this lemma!"
Scott Morrison (Oct 02 2021 at 12:31):
After this,
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) :=
{ hom := λ U V, wedge_morphism U V,
id := λ X, ⟨𝟙 _⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom⟩, }
compiles with no errors.
Scott Morrison (Oct 02 2021 at 12:31):
Okay, but now I am really leaving for the night. :-) Have fun.
fosco (Oct 02 2021 at 12:32):
:-) sure, I will.
Thanks again
fosco (Oct 02 2021 at 13:21):
the same solution, for cowedges, does not work:
@[ext]
lemma wedge_morphism.ext {U V : wedge T} (f g : wedge_morphism U V) (w : f.hom = g.hom) : f = g :=
by { cases f, cases g, tidy, }
@[ext]
lemma cowedge_morphism.ext {U V : cowedge T} (f g : cowedge_morphism U V) (w : f.hom = g.hom) : f = g :=
by { cases f, cases g, tidy, }
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) :=
{ hom := λ U V, wedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom⟩, }
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, cowedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom⟩ }
fosco (Oct 02 2021 at 13:23):
There is an unsolved goal showing that the composition of the hom parts of is a cowedge; something I would easily prove with a couple of cong
s in agda, but here I have no idea how to move
fosco (Oct 02 2021 at 13:23):
...I guess I should move to simpler exercises.
Kevin Buzzard (Oct 02 2021 at 13:27):
Can you paste everything you have so far as a #mwe? I'm only half-watching this thread and so I'm missing all the imports/opens etc, but I can try to help.
Kevin Buzzard (Oct 02 2021 at 13:38):
import category_theory.products.basic
import category_theory.const
open opposite
namespace category_theory
open category_theory.functor
variables {C D E : Type*} [category C] [category D] [category E]
def functor.map_prod (F : C × D ⥤ E) {W X : C} {Y Z : D} (f : W ⟶ X) (g : Y ⟶ Z) :
F.obj (W, Y) ⟶ F.obj (X, Z) :=
F.map (f, g)
structure dinat_trans (F G : Cᵒᵖ × C ⥤ D) :=
(app : Π X, F.obj (op X, X) ⟶ G.obj (op X, X))
(dinaturality : ∀ ⦃X Y : C⦄ (f : X ⟶ Y),
F.map_prod f.op (𝟙 _) ≫ app X ≫ G.map_prod (𝟙 _) f =
F.map_prod (𝟙 _) f ≫ app Y ≫ G.map_prod f.op (𝟙 _) . obviously)
structure wedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans ((const (Cᵒᵖ × C)).obj tip) F)
structure cowedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans F ((const (Cᵒᵖ × C)).obj tip))
variables {T : Cᵒᵖ × C ⥤ D}
structure wedge_morphism (U V : wedge T) :=
(hom : U.tip ⟶ V.tip)
(w' : ∀ j : C, hom ≫ V.α.app j = U.α.app j . obviously)
structure cowedge_morphism (U V : cowedge T) :=
(hom : U.tip ⟶ V.tip)
(w' : ∀ j : C, U.α.app j ≫ hom = V.α.app j . obviously)
restate_axiom wedge_morphism.w'
attribute [simp] wedge_morphism.w
restate_axiom cowedge_morphism.w'
attribute [simp] cowedge_morphism.w
@[ext]
lemma wedge_morphism.ext {U V : wedge T} (f g : wedge_morphism U V) (w : f.hom = g.hom) : f = g :=
by { cases f, cases g, tidy, }
@[ext]
lemma cowedge_morphism.ext {U V : cowedge T} (f g : cowedge_morphism U V) (w : f.hom = g.hom) : f = g :=
by { cases f, cases g, tidy, }
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) :=
{ hom := λ U V, wedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom⟩, }
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, cowedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom⟩ }
-- instance twisted : category (hom C) :=
-- { hom := _,
-- id := _,
-- comp := _,
-- id_comp' := _,
-- comp_id' := _,
-- assoc' := _ }
end category_theory
Kevin Buzzard (Oct 02 2021 at 13:39):
So if I click just before the red underline then I see that the goal is
⊢ ∀ (j : C), X.α.app j ≫ f.hom ≫ g.hom = Z.α.app j
Kevin Buzzard (Oct 02 2021 at 13:41):
so in the definition of composition of morphisms in this cowedge category, so far you have said "let X, Y, Z be objects of cowedge F
and say f : X -> Y
and g : Y -> Z
are morphisms." We now want to define a morphism from X to Z and right now to do that Lean's understanding is that you need to prove (some statement about a diagram commuting)
Kevin Buzzard (Oct 02 2021 at 13:43):
which looks odd to me
Kevin Buzzard (Oct 02 2021 at 13:44):
oh this looks like w'
Kevin Buzzard (Oct 02 2021 at 13:45):
oh, so Lean is complaining that it can't prove w'
Kevin Buzzard (Oct 02 2021 at 13:46):
automation is failing to do your diagram chase
Kevin Buzzard (Oct 02 2021 at 13:46):
Is it true?
Kevin Buzzard (Oct 02 2021 at 13:47):
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, cowedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom, begin
intro j,
sorry
end⟩ }
gives you the goal
F : Cᵒᵖ × C ⥤ D
X Y Z : cowedge F
f : X ⟶ Y
g : Y ⟶ Z
j : C
⊢ X.α.app j ≫ f.hom ≫ g.hom = Z.α.app j
Is that goal true?
Kevin Buzzard (Oct 02 2021 at 13:52):
yeah I can prove it
Kevin Buzzard (Oct 02 2021 at 13:54):
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, cowedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom, begin
intro j,
cases f with f_hom f_w,
cases g with g_hom g_w,
specialize f_w j,
specialize g_w j,
simp [← g_w, ← f_w],
end⟩ }
Kevin Buzzard (Oct 02 2021 at 13:55):
Scott's obviously
tactic seems to find the analogous proof for wedge F
but not for this one. I have no idea how the automation works but there's a hand-constructed proof. It might be the case that with some more magic you can get Lean to find this proof itself
Kevin Buzzard (Oct 02 2021 at 13:57):
and here's what the proof looked like before I golfed it (so you can see my thought process):
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, cowedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom, begin
intro j,
cases f with f_hom f_w,
cases g with g_hom g_w,
simp,
specialize f_w j,
specialize g_w j,
rw ← g_w,
rw ← f_w,
rw category.assoc,
end⟩ }
Kevin Buzzard (Oct 02 2021 at 13:58):
and after:
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, cowedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom, λ j, begin
cases f with _ f_w,
cases g with _ g_w,
simp [← f_w j, ← g_w j],
end⟩ }
fosco (Oct 02 2021 at 14:00):
Amazing!
fosco (Oct 02 2021 at 14:01):
So, when I define a structure like wedge_morphism, cases
allows me to access its fields (hom
and w'
in this case)
Kevin Buzzard (Oct 02 2021 at 14:08):
Yes, and unfortunately (because we are trying to be clever with automation) you can see that the type of f_w
is auto_param (∀ (j : C), X.α.app j ≫ f_hom = Y.α.app j) (name.mk_string "obviously" name.anonymous)
, but I have seen that sufficiently often to know that what it actually says is just ∀ (a : C), X.α.app a ≫ f_hom = Y.α.app a
so I could just feed j
into that function and get X.α.app j ≫ f_hom = Y.α.app j
Kevin Buzzard (Oct 02 2021 at 14:15):
I am bewildered why simp at f_w
doesn't get rid of the auto_param
. rw auto_param_eq at f_w,
gives
rewrite tactic failed, did not find instance of the pattern in the target expression
auto_param ?m_1 ?m_2
state:
...
f_w : auto_param (∀ (j : C), X.α.app j ≫ f_hom = Y.α.app j) (name.mk_string "obviously" name.anonymous),
...
Kevin Buzzard (Oct 02 2021 at 14:16):
Oh I am a fool, it does work, it just leaves the old one behind because it's in the goal (the error above is because there's a second f_w
later on in the context)
Kevin Buzzard (Oct 02 2021 at 14:19):
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, cowedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom, λ j, begin
cases f with _ f_w,
cases g with _ g_w,
simp at ⊢ f_w g_w,
-- local context now looks nice
-- `obviously` still fails though
simp [← f_w j, ← g_w j],
end⟩ }
Adam Topaz (Oct 02 2021 at 14:35):
This works fine for me...
import category_theory.products.basic
import category_theory.const
open opposite
namespace category_theory
open category_theory.functor
variables {C D E : Type*} [category C] [category D] [category E]
def functor.map_prod (F : C × D ⥤ E) {W X : C} {Y Z : D} (f : W ⟶ X) (g : Y ⟶ Z) :
F.obj (W, Y) ⟶ F.obj (X, Z) :=
F.map (f, g)
structure dinat_trans (F G : Cᵒᵖ × C ⥤ D) :=
(app : Π X, F.obj (op X, X) ⟶ G.obj (op X, X))
(dinaturality' : ∀ ⦃X Y : C⦄ (f : X ⟶ Y),
F.map_prod f.op (𝟙 _) ≫ app X ≫ G.map_prod (𝟙 _) f =
F.map_prod (𝟙 _) f ≫ app Y ≫ G.map_prod f.op (𝟙 _) . obviously)
restate_axiom dinat_trans.dinaturality'
attribute [simp, reassoc] dinat_trans.dinaturality
structure wedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans ((const (Cᵒᵖ × C)).obj tip) F)
structure cowedge (F : Cᵒᵖ × C ⥤ D) :=
(tip : D)
(α : dinat_trans F ((const (Cᵒᵖ × C)).obj tip))
variables {T : Cᵒᵖ × C ⥤ D}
structure wedge_morphism (U V : wedge T) :=
(hom : U.tip ⟶ V.tip)
(w' : ∀ j : C, hom ≫ V.α.app j = U.α.app j . obviously)
structure cowedge_morphism (U V : cowedge T) :=
(hom : U.tip ⟶ V.tip)
(w' : ∀ j : C, U.α.app j ≫ hom = V.α.app j . obviously)
restate_axiom wedge_morphism.w'
attribute [simp, reassoc] wedge_morphism.w
restate_axiom cowedge_morphism.w'
attribute [simp, reassoc] cowedge_morphism.w
@[ext]
lemma wedge_morphism.ext {U V : wedge T} (f g : wedge_morphism U V) (w : f.hom = g.hom) : f = g :=
by { cases f, cases g, tidy, }
@[ext]
lemma cowedge_morphism.ext {U V : cowedge T} (f g : cowedge_morphism U V) (w : f.hom = g.hom) : f = g :=
by { cases f, cases g, tidy, }
instance (F : Cᵒᵖ × C ⥤ D) : category (wedge F) :=
{ hom := λ U V, wedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom⟩, }
instance (F : Cᵒᵖ × C ⥤ D) : category (cowedge F) :=
{ hom := λ U V, cowedge_morphism U V,
id := λ X, ⟨ 𝟙 _ ⟩,
comp := λ X Y Z f g, ⟨f.hom ≫ g.hom⟩ }
-- instance twisted : category (hom C) :=
-- { hom := _,
-- id := _,
-- comp := _,
-- id_comp' := _,
-- comp_id' := _,
-- assoc' := _ }
end category_theory
fosco (Oct 02 2021 at 14:37):
The missing part was this
restate_axiom dinat_trans.dinaturality'
attribute [simp, reassoc] dinat_trans.dinaturality
Adam Topaz (Oct 02 2021 at 14:38):
I also added the reassoc attribute to the other simp lemmas
Adam Topaz (Oct 02 2021 at 14:38):
But I don't know exactly what made it work :)
fosco (Oct 02 2021 at 14:39):
lean magic
fosco (Oct 02 2021 at 14:39):
Now: the next step is defining a category having object the hom-class of another given category
fosco (Oct 02 2021 at 14:40):
(probably there is a ton of other things to do, but the twisted arrow category seems to be the next logical step)
Adam Topaz (Oct 02 2021 at 14:40):
We do have docs#category_theory.arrow and docs#category_theory.comma
fosco (Oct 02 2021 at 14:43):
perfect: Tw(C) is the comma category of the terminal functor and of the hom functor of
fosco (Oct 02 2021 at 14:47):
Now, is this an instance or a definition?
Adam Topaz (Oct 02 2021 at 14:48):
docs#category_theory.comma is itself a structure, which is endowed with a category instance
fosco (Oct 02 2021 at 14:51):
I would like to write "given a category C, there is a category Tw(C) done so and so"
fosco (Oct 02 2021 at 14:51):
is this an instance of category, or the definition of a new category?
Johan Commelin (Oct 02 2021 at 14:53):
It's a definition, and you put a category instance on top of it
Johan Commelin (Oct 02 2021 at 14:53):
@[derive category]
def twisted (C : Type*) [category C] := comma _ _ -- fill in the functors
fosco (Oct 02 2021 at 14:57):
It doesn't work:
don't know how to synthesize placeholder
context:
C : Type u_1,
_inst_4 : category C
⊢ Sort ?
fosco (Oct 02 2021 at 14:57):
(also, unknown identifier comma
, but that's going to be solved with the right open
I guess)
Adam Topaz (Oct 02 2021 at 14:58):
You're probably missing an import
Adam Topaz (Oct 02 2021 at 14:58):
What are the two functors precisely? The initial one from *, but what do you mean by the hom functor?
Adam Topaz (Oct 02 2021 at 14:59):
The one from Cop x C to Set?
fosco (Oct 02 2021 at 14:59):
the functor sending to and $(u,v)$ to the function
fosco (Oct 02 2021 at 15:01):
but I would like to re-define these basic objects, and refactor later using more high-level stuff... I feel I'm losing the grip of the problem.
fosco (Oct 02 2021 at 15:01):
I need baby steps. How do I define a category with a single object and a single morphism?
fosco (Oct 02 2021 at 15:01):
how do I define a functor from said category to Set, picking the singleton set?
fosco (Oct 02 2021 at 15:02):
when I have these blocks, and the hom functor above, I can try to define twisted
Adam Topaz (Oct 02 2021 at 15:04):
Gotcha. So we have the constant functor as you already know, and for the hom functor we can use docs#category_theory.yoneda and docs#category_theory.uncurry (and docs#category_theory.prod.swap if needed)
fosco (Oct 02 2021 at 15:06):
yoneda + uncurry gives hom, I understand, but what about the terminal category?
Adam Topaz (Oct 02 2021 at 15:06):
docs#category_theory.discrete and docs#punit
Adam Topaz (Oct 02 2021 at 15:07):
so category_theory.discrete punit
is the terminal category
fosco (Oct 02 2021 at 15:09):
def hom_functor : Cᵒᵖ × C ⥤ Type* :=
uncurry yoneda
def terminal_category : category unit :=
category_theory.discrete punit
I have no idea what I'm doing :grinning:
fosco (Oct 02 2021 at 15:10):
(mostly because I have no idea how to write the generic "this is of type that")
Johan Commelin (Oct 02 2021 at 15:12):
@fosco what do you mean?
Johan Commelin (Oct 02 2021 at 15:13):
def terminal_category : category unit :=
category_theory.discrete_category punit
:this: should be instance
. You are instructing lean how to put a category structure on the type unit
.
Johan Commelin (Oct 02 2021 at 15:14):
But you can also just use category_theory.discrete punit
, as Adam suggested.
category_theory.discrete
is a function that eats a type, and spits out that same type (the identity, ha!)
But the upshot is that if a type is wrapped in this identity function, then Lean endows it with the category structure that has no homs except for the identity homs.
fosco (Oct 02 2021 at 15:16):
No: category_theory.discrete punit
throws a mismatch
fosco (Oct 02 2021 at 15:16):
category_theory.discrete_category punit
does not
fosco (Oct 02 2021 at 15:17):
Johan Commelin said:
fosco what do you mean?
I mean that I have no idea how to turn into Lean the definition I have in mind
fosco (Oct 02 2021 at 15:18):
I see there's a lot of stuff already written, but I feel like I'm the passenger in a bus; when the trip is finished I don't remember the road I took. I learn by driving.
fosco (Oct 02 2021 at 15:19):
My problem is small, and I want an elementary solution; I don't care there is a library that does it already, I need to see how to write down the definition I want
fosco (Oct 02 2021 at 15:19):
You are helping a lot, but it is exhausting to say the least.
fosco (Oct 02 2021 at 15:19):
I want to define a category with a single object and a single morphism. I want to define a functor from it to Set, that picks the singleton
Johan Commelin (Oct 02 2021 at 15:21):
So you write
instance : category unit :=
_
And use the :bulb: to get a skeleton.
Johan Commelin (Oct 02 2021 at 15:21):
After that, you write
def terminal_functor : unit ⥤ Type :=
_
etc...
fosco (Oct 02 2021 at 15:33):
ok, I'll give it a try. But now I need a break
Thanks!
Adam Topaz (Oct 02 2021 at 16:46):
I made you a video explaining how to construct these things:
2021-10-02_10-31-46.mkv
fosco (Oct 02 2021 at 17:12):
wow, many thanks!
Adam Topaz (Oct 02 2021 at 17:18):
No problem. There are a few subtleties with universe parameters, as you can see...
fosco (Oct 02 2021 at 17:34):
heh, yeah :grinning: I would have lost a few hours after those...
Scott Morrison (Oct 03 2021 at 00:09):
Just coming back to explain why the reassoc
attribute Adam suggested is useful!
Scott Morrison (Oct 03 2021 at 00:10):
The goal automation was stuck on was
F : Cᵒᵖ × C ⥤ D
X Y Z : cowedge F
f : X ⟶ Y
g : Y ⟶ Z
j : C
⊢ X.α.app j ≫ f.hom ≫ g.hom = Z.α.app j
Scott Morrison (Oct 03 2021 at 00:11):
You might wonder: surely f.w : X.α.app j ≫ f.hom = Y.α.app j
, which is a @[simp]
lemma, should fire here when automation calls simp
, reducing the goal to Y.α.app j ≫ g.hom = Z.α.app j
, which is in turn solvable by simp
using g.w
.
Scott Morrison (Oct 03 2021 at 00:12):
The problem is associativity: the goal is actually X.α.app j ≫ (f.hom ≫ g.hom)
= Z.α.app j and so
f.w` doesn't immediately apply.
Scott Morrison (Oct 03 2021 at 00:12):
We could deal with this problem by hand, by rewriting using category.assoc
to rebracket and then using f.w
and g.w
.
Scott Morrison (Oct 03 2021 at 00:14):
However we could also realise that it would be helpful if there was a lemma f.w_assoc : ∀ h, X.α.app j ≫ (f.hom ≫ h) = Y.α.app j ≫ h
, where we are quantifying over some arbitrary other morphism h
.
Scott Morrison (Oct 03 2021 at 00:15):
If this were a @[simp]
lemma, then simp
could discharge the original goal by using f.w_assoc g.hom
, and then using g.w
.
Scott Morrison (Oct 03 2021 at 00:16):
Writing attribute [reassoc] wedge_morphism.w
achieves exactly this! The reassoc attribute causes Lean to go away and inspect the lemma, realise it is an equation in a category involving a composition on the LHS, and automatically generate the additional lemma wedge_morphism.w_assoc
.
Scott Morrison (Oct 03 2021 at 00:16):
In fact, you should try writing #print wedge_morphism.w_assoc
to verify that this lemma was automatically created, and behaves as I indicated.
Scott Morrison (Oct 03 2021 at 00:18):
This trick largely ameliorates dealing with associativity in 1-categories. We can work with all our expressions in "simp normal form", here meaning "all associated to the right", but lemmas about compositions have automatically generated helper lemmas that allow them to apply in the middle of a composition.
Scott Morrison (Oct 03 2021 at 00:20):
(Sadly we have not implemented the planar-graph-pattern-matching that would be required to do this in 2-categories / monoidal categories. :-) One day!)
fosco (Oct 03 2021 at 08:47):
Thanks a lot! So, next step is define the twisted arrow category of C
fosco (Oct 03 2021 at 08:48):
I need
- the hom functor:
- the terminal functor, choosing the singleton
- a comma construction.
I have 2. 1 can be obtained uncurrying yoneda. 3 is already there
fosco (Oct 03 2021 at 08:49):
This is not what I initially wanted to use to define Tw(C), but nevermind, maybe there will be a theorem later.
Scott Morrison (Oct 03 2021 at 08:50):
Remember that Set
is called Type
now. :-)
Scott Morrison (Oct 03 2021 at 08:51):
See category_theory.hom_functor
: src#category_theory.functor.hom
Scott Morrison (Oct 03 2021 at 08:55):
We also have src#category_theory.category_of_elements.
Scott Morrison (Oct 03 2021 at 08:56):
which might give you a one-liner definition of the twisted arrow category!
fosco (Oct 03 2021 at 08:57):
The problem is always the same, I don't know the syntax with which I can invoke the right definition
fosco (Oct 03 2021 at 08:58):
Plus, copy-pasting the definition of hom results in errors
fosco (Oct 03 2021 at 09:00):
failed to synthesize type class instance for
C : Type u_1,
_inst_1 : category C,
p : Cᵒᵖ × C
⊢ quiver C
Scott Morrison (Oct 03 2021 at 09:00):
That's weird!
Scott Morrison (Oct 03 2021 at 09:00):
Can you post a #mwe?
Scott Morrison (Oct 03 2021 at 09:00):
Or try set_option pp.universes true
and see what the error message becomes?
fosco (Oct 03 2021 at 09:01):
Where should I put it?
Kevin Buzzard (Oct 03 2021 at 09:01):
Before the error
Kevin Buzzard (Oct 03 2021 at 09:02):
Outside any structure def or theorem
Kevin Buzzard (Oct 03 2021 at 09:02):
But you should please get into the habit of posting #mwe s. Errors by themselves are not easy to interpret
fosco (Oct 03 2021 at 09:03):
import category_theory.products.basic
import category_theory.const
import category_theory.comma
import category_theory.discrete_category
open opposite
namespace category_theory
open category_theory.functor
variables {C D E : Type*} [category C] [category D] [category E]
definition hom : Cᵒᵖ × C ⥤ Type :=
{ obj := λ p, unop p.1 ⟶ p.2,
map := λ X Y f, λ h, f.1.unop ≫ h ≫ f.2 }
end category_theory
fosco (Oct 03 2021 at 09:03):
Scott Morrison (Oct 03 2021 at 09:04):
Ah, but you didn't copy and paste.
Scott Morrison (Oct 03 2021 at 09:04):
You wrote Type
as the target.
Scott Morrison (Oct 03 2021 at 09:04):
The problem is that [category C]
introduces a universe variable for the morphism level.
Scott Morrison (Oct 03 2021 at 09:05):
import category_theory.products.basic
import category_theory.const
import category_theory.comma
import category_theory.discrete_category
open opposite
namespace category_theory
open category_theory.functor
variables {C D E : Type*} [category C] [category D] [category E]
definition hom : Cᵒᵖ × C ⥤ Type* :=
{ obj := λ p, unop p.1 ⟶ p.2,
map := λ X Y f, λ h, f.1.unop ≫ h ≫ f.2 }
end category_theory
works fine.
Scott Morrison (Oct 03 2021 at 09:05):
Alternatively if we write
import category_theory.products.basic
import category_theory.const
import category_theory.comma
import category_theory.discrete_category
open opposite
namespace category_theory
open category_theory.functor
variables {C D E : Type*} [category C] [category D] [category E]
set_option pp.universes true
definition hom : Cᵒᵖ × C ⥤ Type :=
{ obj := λ p, unop p.1 ⟶ p.2,
map := λ X Y f, λ h, f.1.unop ≫ h ≫ f.2 }
end category_theory
Scott Morrison (Oct 03 2021 at 09:05):
we get a useful error message:
Scott Morrison (Oct 03 2021 at 09:06):
failed to synthesize type class instance for
C : Type u_1,
_inst_1 : category.{u_4 u_1} C,
p : Cᵒᵖ × C
⊢ quiver.{1 u_1} C
Scott Morrison (Oct 03 2021 at 09:06):
From which you can see that there is a universe level problem! There is a category instance with universe levels .{u_4 u_1}
, but the quiver instance you need is .{1 u_1}
.
Scott Morrison (Oct 03 2021 at 09:07):
and the reason for this is exactly that you changed the codomain of hom
to Type
.
Kevin Buzzard (Oct 03 2021 at 09:08):
You have to ask yourself whether you want to work with a category C whose objects form a set in some Grothendieck universe u1 and whose hom sets all live in another Grothendieck universe u2, and then whether D has objects in u3 etc etc. That's what you're doing right now
Scott Morrison (Oct 03 2021 at 09:08):
The one-liner for twisted_arrow
is just:
fosco (Oct 03 2021 at 09:09):
I see! Thanks.
Kevin Buzzard (Oct 03 2021 at 09:09):
Type is the smallest Grothendieck universe so you can't land in there in general unless you restrict to categories whose hom sets are there. Basically you have to decide what you mean by a category, is it small, large, or do you want to try to write code which works for both or even more general situations
Kevin Buzzard (Oct 03 2021 at 09:10):
Right now we choose a universe level for objects and a different one for morphisms
Scott Morrison (Oct 03 2021 at 09:11):
(Hopefully reading the note about universe levels in category_theory.category.basic
will be helpful. It explains why we need to use two independent universe levels, in order to formalise small and large categories uniformly.)
Patrick Massot (Oct 03 2021 at 09:13):
https://leanprover-community.github.io/mathlib_docs/notes.html#category_theory%20universes
fosco (Oct 03 2021 at 09:15):
Kevin Buzzard said:
In lean we choose a universe level for objects and a different one for morphisms
Yes; whereas usually objects are in a universe more than the one where hom's live
fosco (Oct 03 2021 at 09:15):
anyway
fosco (Oct 03 2021 at 09:18):
now I have various choices for how to formalise next:
- the end of F is the terminal object of its category of wedges
- precomposing with the functor sends to , and
fosco (Oct 03 2021 at 09:20):
-
I looked for "terminal object of a category", but I didn't find anything, only the statement that a category has a terminal object. I was thinking to something on the lines of "{Wd(F) has a terminal object, a choice of that object}"
-
does the category of elements construction allows to extract the functor immediately?
Scott Morrison (Oct 03 2021 at 09:21):
- does the category of elements construction allows to extract the functor immediately?
Which functor?
fosco (Oct 03 2021 at 09:22):
there are various ways to call it; the "category of elements" construction turns a presheaf into a fibration over ; the functor I want is precisely that fibration
Scott Morrison (Oct 03 2021 at 09:22):
1.
src#category_theory.limits.is_terminal
fosco (Oct 03 2021 at 09:23):
it just forgets the "element" a in (X, a \in FX)
Scott Morrison (Oct 03 2021 at 09:23):
src#category_theory.category_of_elements.π
Scott Morrison (Oct 03 2021 at 09:23):
(or just read through category_theory.elements
until you find it :-)
fosco (Oct 03 2021 at 09:26):
def twisted_fibration : twisted C ⥤ Cᵒᵖ × C :=
category_of_elements.π (twisted C)
I get a universe error.. let's see if I'm able to fix it alone
fosco (Oct 03 2021 at 09:27):
no, it's a type misatch
fosco (Oct 03 2021 at 09:27):
twisted C
has type
Type (max u_1 u_4) : Type (max (u_1+1) (u_4+1))
but is expected to have type
Cᵒᵖ × C ⥤ Type u_4 : Type (max u_4 u_1 (u_4+1))
fosco (Oct 03 2021 at 09:28):
def twisted_fibration : twisted C ⥤ Cᵒᵖ × C :=
category_of_elements.π (functor.hom C)
hooray!
fosco (Oct 03 2021 at 09:30):
Now:
/- TODO:
F : Cᵒᵖ × C ⥤ D (I'd be happy to do it just for D=Type* atm...)
end1 : the terminal object in Wd(F) (it exists, because Type is complete)
end2 : limit of (F ⋙ twisted_fibration C)
thm end1 ≅ end2 canonically
-/
fosco (Oct 03 2021 at 09:31):
( whoops, it's (twisted_fibration C ⋙ F)
)
Scott Morrison (Oct 03 2021 at 09:39):
Oh dear, you've said the dread word "canonically"! What do you mean? :-)
Scott Morrison (Oct 03 2021 at 09:41):
Presumably it is some naturality statement with respect to C
.
fosco (Oct 03 2021 at 09:41):
yes (it can be done later, or it can be avoided :grinning: I'm suffering enough)
fosco (Oct 03 2021 at 09:41):
def end1 (F : Cᵒᵖ × C ⥤ Type*) : Type* := sorry
def end2 (F : Cᵒᵖ × C ⥤ Type*) : Type* := sorry
fosco (Oct 03 2021 at 09:42):
these are the typings.
Scott Morrison (Oct 03 2021 at 09:42):
So yes, first challenge is to write down the statement of the isomorphism, with a sorry for the construction.
fosco (Oct 03 2021 at 09:43):
Whoops, no
Scott Morrison (Oct 03 2021 at 09:44):
We'd like to just be able to write ⊤ : wedge F
to specify the terminal object. Probably we're going to have to do some amount of explaining so that Lean understands why the completeness of Type
implies the existence of a terminal object in wedge F
.
fosco (Oct 03 2021 at 09:44):
oh, so \top is a shorthand to refer to a terminal object?
Scott Morrison (Oct 03 2021 at 09:45):
Yes. It's used all over mathlib for the top element of a lattice, but we also use the same notation for terminal objects.
fosco (Oct 03 2021 at 09:46):
How comes I can't find it if I Ctrl-F the entire src/ folder?
Scott Morrison (Oct 03 2021 at 09:46):
Are you writing \top in the search box? You need to copy and paste the unicode symbol into the search box.
fosco (Oct 03 2021 at 09:46):
Yes, I did
Scott Morrison (Oct 03 2021 at 09:47):
Does searching for anything work?
fosco (Oct 03 2021 at 09:50):
Nevermind; in theory this should work
limits.terminal (wedge F)
but it complains because it wants a proof that Type* has enough limits (probably?)
Scott Morrison (Oct 03 2021 at 09:50):
No, it's not clever enough to want that. :-)
Scott Morrison (Oct 03 2021 at 09:50):
How is Lean going to know anything about any limits in wedge F
?
Scott Morrison (Oct 03 2021 at 09:51):
As far as it is concerned it is some brand new category.
Scott Morrison (Oct 03 2021 at 09:51):
We need to tell it something. So --- why does wedge F
have a terminal object?
fosco (Oct 03 2021 at 09:51):
it doesn't; but __if__ it does, that's the end.
fosco (Oct 03 2021 at 09:52):
Scott Morrison said:
How is Lean going to know anything about any limits in
wedge F
?
Of course :smile:
fosco (Oct 03 2021 at 09:52):
that's why I was thinking about something like {a proof that wedge(F) has a terminal object, a choice of that object}
fosco (Oct 03 2021 at 09:52):
but this is a.. structure?
Scott Morrison (Oct 03 2021 at 09:53):
So you need is_terminal
fosco (Oct 03 2021 at 09:54):
is_terminal
eats an object of the codomain
Scott Morrison (Oct 03 2021 at 09:54):
def my_iso {F : Cᵒᵖ × C ⥤ D} (X : wedge F) (h : is_terminal X) : P ≅ Q := sorry
Scott Morrison (Oct 03 2021 at 09:54):
That says: "suppose I have a terminal wedge, called X, then I can construct an isomorphism between P and Q"
Scott Morrison (Oct 03 2021 at 09:54):
(obviously you will need to fill in P and Q here)
fosco (Oct 03 2021 at 09:55):
I don't understand...
Scott Morrison (Oct 03 2021 at 09:57):
Isn't this what you want to say? You want to say "Suppose there is a terminal object in wedge F. Then <some construction based on that object> is a limit for twisted_fibration C ⋙ F
."
fosco (Oct 03 2021 at 09:58):
oh! I see; no, I'm stuck at a former step, defining the end of F. I took another approach, but it looks kinda stupid
def end1 (F : Cᵒᵖ × C ⥤ D) (X : wedge F) (h : limits.is_terminal X) : wedge F := X
fosco (Oct 03 2021 at 09:58):
at least it doesnt complain...
Scott Morrison (Oct 03 2021 at 09:58):
So maybe instead you want to write
def limit_cone_of_terminal_wedge {F : Cᵒᵖ × C ⥤ D} (X : wedge F) (h : is_terminal X) :
cone (twisted_fibration C ⋙ F) :=
...
lemma is_limit_of_terminal_wedge {F : Cᵒᵖ × C ⥤ D} (X : wedge F) (h : is_terminal X) :
is_limit (limit_cone_of_terminal_wedge X h) :=
...
Scott Morrison (Oct 03 2021 at 09:59):
Yeah, that end1
definition is not doing anything for you. :-)
Scott Morrison (Oct 03 2021 at 10:01):
And probably you want to factor that into more pieces:
def end_of_terminal_wedge {F : Cᵒᵖ × C ⥤ D} (X : wedge F) (h : is_terminal X) : D :=
sorry
@[simps]
def limit_cone_of_terminal_wedge {F : Cᵒᵖ × C ⥤ D} (X : wedge F) (h : is_terminal X) :
cone (twisted_fibration C ⋙ F) :=
{ X := end_of_terminal_wedge X h,
π := sorry, }
lemma is_limit_of_terminal_wedge {F : Cᵒᵖ × C ⥤ D} (X : wedge F) (h : is_terminal X) :
is_limit (limit_cone_of_terminal_wedge X h) :=
...
fosco (Oct 03 2021 at 10:02):
well, technically the end of F is the whole wedge, an object of wedge F
fosco (Oct 03 2021 at 10:02):
usually you call "the end" just the tip
fosco (Oct 03 2021 at 10:03):
I need a break :grinning: thanks for your help so far!
Scott Morrison (Oct 03 2021 at 10:52):
@fosco, rather than this manual translation between terminal objects and limit cones, you should just directly prove the equivalence of categories between wedge F
and cone (twisted_fibration C ⋙ F)
.
Kevin Buzzard (Oct 03 2021 at 11:20):
Yes; whereas usually objects are in a universe more than the one where hom's live
You're claiming that, but you're also talking about limits and for limits in large categories it's essential that the source category (the diagram) does not satisfy the condition you claim is usual. And limits are also "usual" right? Formalisation has to take these things into account and it's when you start formalising that you start noticing them.
Kevin Buzzard (Oct 03 2021 at 11:22):
The way Scott has set it up saves us from having to develop two parallel theories of small and large categories.
Kevin Buzzard (Oct 03 2021 at 11:29):
It is not true in lean that "every small category is large", for the same reason that it's not true in lean that every natural number is a real number. There's a "canonical" construction which eats one thing and spits out the other but it's a genuine function and needs to be applied (and then one has to check that it commutes with everything)
Last updated: Dec 20 2023 at 11:08 UTC