Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit bd385fb

Browse files
committed
chore(category_theory/limits/functor_category): shuffle limits in functor cats (#4124)
Give `is_limit` versions for statements about limits in the functor category, and write the `has_limit` versions in terms of those. This also generalises the universes a little. As usual, suggestions for better docstrings or better names appreciated!
1 parent 5d35e62 commit bd385fb

File tree

2 files changed

+102
-65
lines changed

2 files changed

+102
-65
lines changed

src/category_theory/limits/cones.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ structure cone (F : J ⥤ C) :=
8484
(X : C)
8585
(π : (const J).obj X ⟶ F)
8686

87-
@[simp] lemma cone.w {F : J ⥤ C} (c : cone F) {j j' : J} (f : j ⟶ j') :
87+
@[simp, reassoc] lemma cone.w {F : J ⥤ C} (c : cone F) {j j' : J} (f : j ⟶ j') :
8888
c.π.app j ≫ F.map f = c.π.app j' :=
8989
by { rw ← (c.π.naturality f), apply id_comp }
9090

@@ -99,7 +99,7 @@ structure cocone (F : J ⥤ C) :=
9999
(X : C)
100100
(ι : F ⟶ (const J).obj X)
101101

102-
@[simp] lemma cocone.w {F : J ⥤ C} (c : cocone F) {j j' : J} (f : j ⟶ j') :
102+
@[simp, reassoc] lemma cocone.w {F : J ⥤ C} (c : cocone F) {j j' : J} (f : j ⟶ j') :
103103
F.map f ≫ c.ι.app j' = c.ι.app j :=
104104
by { rw (c.ι.naturality f), apply comp_id }
105105

src/category_theory/limits/functor_category.lean

Lines changed: 100 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -7,87 +7,124 @@ import category_theory.limits.preserves.basic
77

88
open category_theory category_theory.category
99

10-
noncomputable theory
11-
1210
namespace category_theory.limits
1311

14-
universes v u -- declare the `v`'s first; see `category_theory.category` for an explanation
12+
universes v v₂ u -- declare the `v`'s first; see `category_theory.category` for an explanation
1513

1614
variables {C : Type u} [category.{v} C]
1715

18-
variables {J K : Type v} [small_category J] [small_category K]
19-
20-
@[simp] lemma cone.functor_w {F : J ⥤ (K ⥤ C)} (c : cone F) {j j' : J} (f : j ⟶ j') (k : K) :
21-
(c.π.app j).app k ≫ (F.map f).app k = (c.π.app j').app k :=
22-
by convert ←nat_trans.congr_app (c.π.naturality f).symm k; apply id_comp
16+
variables {J K : Type v} [small_category J] [category.{v₂} K]
2317

24-
@[simp] lemma cocone.functor_w {F : J ⥤ (K ⥤ C)} (c : cocone F) {j j' : J} (f : j ⟶ j') (k : K) :
25-
(F.map f).app k ≫ (c.ι.app j').app k = (c.ι.app j).app k :=
26-
by convert ←nat_trans.congr_app (c.ι.naturality f) k; apply comp_id
27-
28-
@[simps] def functor_category_limit_cone [has_limits_of_shape J C] (F : J ⥤ K ⥤ C) :
18+
/--
19+
The evaluation functors jointly reflect limits: that is, to show a cone is a limit of `F`
20+
it suffices to show that each evaluation cone is a limit. In other words, to prove a cone is
21+
limiting you can show it's pointwise limiting.
22+
-/
23+
def evaluation_jointly_reflects_limits {F : J ⥤ K ⥤ C} (c : cone F)
24+
(t : Π (k : K), is_limit (((evaluation K C).obj k).map_cone c)) : is_limit c :=
25+
{ lift := λ s,
26+
{ app := λ k, (t k).lift ⟨s.X.obj k, whisker_right s.π ((evaluation K C).obj k)⟩,
27+
naturality' := λ X Y f, (t Y).hom_ext $ λ j,
28+
begin
29+
rw [assoc, (t Y).fac _ j],
30+
simpa using ((t X).fac_assoc ⟨s.X.obj X, whisker_right s.π ((evaluation K C).obj X)⟩ j _).symm,
31+
end },
32+
fac' := λ s j, nat_trans.ext _ _ $ funext $ λ k, (t k).fac _ j,
33+
uniq' := λ s m w, nat_trans.ext _ _ $ funext $ λ x, (t x).hom_ext $ λ j,
34+
(congr_app (w j) x).trans
35+
((t x).fac ⟨s.X.obj _, whisker_right s.π ((evaluation K C).obj _)⟩ j).symm }
36+
37+
/--
38+
Given a functor `F` and a collection of limit cones for each diagram `X ↦ F X k`, we can stitch
39+
them together to give a cone for the diagram `F`.
40+
`combined_is_limit` shows that the new cone is limiting, and `eval_combined` shows it is
41+
(essentially) made up of the original cones.
42+
-/
43+
@[simps] def combine_cones (F : J ⥤ K ⥤ C) (c : Π (k : K), limit_cone (F.flip.obj k)) :
2944
cone F :=
30-
{ X := F.flip ⋙ lim,
45+
{ X :=
46+
{ obj := λ k, (c k).cone.X,
47+
map := λ k₁ k₂ f, (c k₂).is_limit.lift ⟨_, (c k₁).cone.π ≫ F.flip.map f⟩,
48+
map_id' := λ k, (c k).is_limit.hom_ext (λ j, by { dsimp, simp }),
49+
map_comp' := λ k₁ k₂ k₃ f₁ f₂, (c k₃).is_limit.hom_ext (λ j, by simp) },
3150
π :=
32-
{ app := λ j,
33-
{ app := λ k, limit.π (F.flip.obj k) j },
34-
naturality' := λ j j' f,
35-
by ext k; convert (limit.w (F.flip.obj k) _).symm using 1; apply id_comp } }
51+
{ app := λ j, { app := λ k, (c k).cone.π.app j },
52+
naturality' := λ j₁ j₂ g, nat_trans.ext _ _ $ funext $ λ k, (c k).cone.π.naturality g } }
53+
54+
/-- The stitched together cones each project down to the original given cones (up to iso). -/
55+
def evaluate_combined_cones (F : J ⥤ K ⥤ C) (c : Π (k : K), limit_cone (F.flip.obj k)) (k : K) :
56+
((evaluation K C).obj k).map_cone (combine_cones F c) ≅ (c k).cone :=
57+
cones.ext (iso.refl _) (by tidy)
3658

37-
@[simps] def functor_category_colimit_cocone [has_colimits_of_shape J C] (F : J ⥤ K ⥤ C) :
59+
/-- Stitching together limiting cones gives a limiting cone. -/
60+
def combined_is_limit (F : J ⥤ K ⥤ C) (c : Π (k : K), limit_cone (F.flip.obj k)) :
61+
is_limit (combine_cones F c) :=
62+
evaluation_jointly_reflects_limits _
63+
(λ k, (c k).is_limit.of_iso_limit (evaluate_combined_cones F c k).symm)
64+
65+
/--
66+
The evaluation functors jointly reflect colimits: that is, to show a cocone is a colimit of `F`
67+
it suffices to show that each evaluation cocone is a colimit. In other words, to prove a cocone is
68+
colimiting you can show it's pointwise colimiting.
69+
-/
70+
def evaluation_jointly_reflects_colimits {F : J ⥤ K ⥤ C} (c : cocone F)
71+
(t : Π (k : K), is_colimit (((evaluation K C).obj k).map_cocone c)) : is_colimit c :=
72+
{ desc := λ s,
73+
{ app := λ k, (t k).desc ⟨s.X.obj k, whisker_right s.ι ((evaluation K C).obj k)⟩,
74+
naturality' := λ X Y f, (t X).hom_ext $ λ j,
75+
begin
76+
rw [(t X).fac_assoc _ j],
77+
erw ← (c.ι.app j).naturality_assoc f,
78+
erw (t Y).fac ⟨s.X.obj _, whisker_right s.ι _⟩ j,
79+
dsimp,
80+
simp,
81+
end },
82+
fac' := λ s j, nat_trans.ext _ _ $ funext $ λ k, (t k).fac _ j,
83+
uniq' := λ s m w, nat_trans.ext _ _ $ funext $ λ x, (t x).hom_ext $ λ j,
84+
(congr_app (w j) x).trans
85+
((t x).fac ⟨s.X.obj _, whisker_right s.ι ((evaluation K C).obj _)⟩ j).symm }
86+
87+
/--
88+
Given a functor `F` and a collection of colimit cocones for each diagram `X ↦ F X k`, we can stitch
89+
them together to give a cocone for the diagram `F`.
90+
`combined_is_colimit` shows that the new cocone is colimiting, and `eval_combined` shows it is
91+
(essentially) made up of the original cocones.
92+
-/
93+
@[simps] def combine_cocones (F : J ⥤ K ⥤ C) (c : Π (k : K), colimit_cocone (F.flip.obj k)) :
3894
cocone F :=
39-
{ X := F.flip ⋙ colim,
95+
{ X :=
96+
{ obj := λ k, (c k).cocone.X,
97+
map := λ k₁ k₂ f, (c k₁).is_colimit.desc ⟨_, F.flip.map f ≫ (c k₂).cocone.ι⟩,
98+
map_id' := λ k, (c k).is_colimit.hom_ext (λ j, by { dsimp, simp }),
99+
map_comp' := λ k₁ k₂ k₃ f₁ f₂, (c k₁).is_colimit.hom_ext (λ j, by simp) },
40100
ι :=
41-
{ app := λ j,
42-
{ app := λ k, colimit.ι (F.flip.obj k) j },
43-
naturality' := λ j j' f,
44-
by ext k; convert (colimit.w (F.flip.obj k) _) using 1; apply comp_id } }
45-
46-
@[simp] def evaluate_functor_category_limit_cone
47-
[has_limits_of_shape J C] (F : J ⥤ K ⥤ C) (k : K) :
48-
((evaluation K C).obj k).map_cone (functor_category_limit_cone F) ≅
49-
limit.cone (F.flip.obj k) :=
50-
cones.ext (iso.refl _) (by tidy)
101+
{ app := λ j, { app := λ k, (c k).cocone.ι.app j },
102+
naturality' := λ j₁ j₂ g, nat_trans.ext _ _ $ funext $ λ k, (c k).cocone.ι.naturality g } }
51103

52-
@[simp] def evaluate_functor_category_colimit_cocone
53-
[has_colimits_of_shape J C] (F : J ⥤ K ⥤ C) (k : K) :
54-
((evaluation K C).obj k).map_cocone (functor_category_colimit_cocone F) ≅
55-
colimit.cocone (F.flip.obj k) :=
104+
/-- The stitched together cocones each project down to the original given cocones (up to iso). -/
105+
def evaluate_combined_cocones (F : J ⥤ K ⥤ C) (c : Π (k : K), colimit_cocone (F.flip.obj k)) (k : K) :
106+
((evaluation K C).obj k).map_cocone (combine_cocones F c) ≅ (c k).cocone :=
56107
cocones.ext (iso.refl _) (by tidy)
57108

58-
def functor_category_is_limit_cone [has_limits_of_shape J C] (F : J ⥤ K ⥤ C) :
59-
is_limit (functor_category_limit_cone F) :=
60-
{ lift := λ s,
61-
{ app := λ k, limit.lift (F.flip.obj k) (((evaluation K C).obj k).map_cone s) },
62-
uniq' := λ s m w,
63-
begin
64-
ext1, ext1 k,
65-
exact is_limit.uniq _
66-
(((evaluation K C).obj k).map_cone s) (m.app k) (λ j, nat_trans.congr_app (w j) k)
67-
end }
68-
69-
def functor_category_is_colimit_cocone [has_colimits_of_shape J C] (F : J ⥤ K ⥤ C) :
70-
is_colimit (functor_category_colimit_cocone F) :=
71-
{ desc := λ s,
72-
{ app := λ k, colimit.desc (F.flip.obj k) (((evaluation K C).obj k).map_cocone s) },
73-
uniq' := λ s m w,
74-
begin
75-
ext1, ext1 k,
76-
exact is_colimit.uniq _
77-
(((evaluation K C).obj k).map_cocone s) (m.app k) (λ j, nat_trans.congr_app (w j) k)
78-
end }
109+
/-- Stitching together colimiting cocones gives a colimiting cocone. -/
110+
def combined_is_colimit (F : J ⥤ K ⥤ C) (c : Π (k : K), colimit_cocone (F.flip.obj k)) :
111+
is_colimit (combine_cocones F c) :=
112+
evaluation_jointly_reflects_colimits _
113+
(λ k, (c k).is_colimit.of_iso_colimit (evaluate_combined_cocones F c k).symm)
114+
115+
noncomputable theory
79116

80117
instance functor_category_has_limits_of_shape
81118
[has_limits_of_shape J C] : has_limits_of_shape J (K ⥤ C) :=
82119
{ has_limit := λ F, has_limit.mk
83-
{ cone := functor_category_limit_cone F,
84-
is_limit := functor_category_is_limit_cone F } }
120+
{ cone := combine_cones F (λ k, get_limit_cone _),
121+
is_limit := combined_is_limit _ _ } }
85122

86123
instance functor_category_has_colimits_of_shape
87124
[has_colimits_of_shape J C] : has_colimits_of_shape J (K ⥤ C) :=
88125
{ has_colimit := λ F, has_colimit.mk
89-
{ cocone := functor_category_colimit_cocone F,
90-
is_colimit := functor_category_is_colimit_cocone F } }
126+
{ cocone := combine_cocones _ (λ k, get_colimit_cocone _),
127+
is_colimit := combined_is_colimit _ _ } }
91128

92129
instance functor_category_has_limits [has_limits C] : has_limits (K ⥤ C) :=
93130
{ has_limits_of_shape := λ J 𝒥, by resetI; apply_instance }
@@ -98,16 +135,16 @@ instance functor_category_has_colimits [has_colimits C] : has_colimits (K ⥤ C)
98135
instance evaluation_preserves_limits_of_shape [has_limits_of_shape J C] (k : K) :
99136
preserves_limits_of_shape J ((evaluation K C).obj k) :=
100137
{ preserves_limit :=
101-
λ F, preserves_limit_of_preserves_limit_cone (functor_category_is_limit_cone _) $
138+
λ F, preserves_limit_of_preserves_limit_cone (combined_is_limit _ _) $
102139
is_limit.of_iso_limit (limit.is_limit _)
103-
(evaluate_functor_category_limit_cone F k).symm }
140+
(evaluate_combined_cones F _ k).symm }
104141

105142
instance evaluation_preserves_colimits_of_shape [has_colimits_of_shape J C] (k : K) :
106143
preserves_colimits_of_shape J ((evaluation K C).obj k) :=
107144
{ preserves_colimit :=
108-
λ F, preserves_colimit_of_preserves_colimit_cocone (functor_category_is_colimit_cocone _) $
145+
λ F, preserves_colimit_of_preserves_colimit_cocone (combined_is_colimit _ _) $
109146
is_colimit.of_iso_colimit (colimit.is_colimit _)
110-
(evaluate_functor_category_colimit_cocone F k).symm }
147+
(evaluate_combined_cocones F _ k).symm }
111148

112149
instance evaluation_preserves_limits [has_limits C] (k : K) :
113150
preserves_limits ((evaluation K C).obj k) :=

0 commit comments

Comments
 (0)