-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathComma.lean
More file actions
319 lines (251 loc) · 12.9 KB
/
Comma.lean
File metadata and controls
319 lines (251 loc) · 12.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/-
Copyright (c) 2021 Bhavik Mehta. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Bhavik Mehta
-/
module
public import Mathlib.CategoryTheory.Comma.Arrow
public import Mathlib.CategoryTheory.Comma.Over.Basic
public import Mathlib.CategoryTheory.Limits.Constructions.EpiMono
public import Mathlib.CategoryTheory.Limits.Creates
public import Mathlib.CategoryTheory.Limits.Unit
/-!
# Limits and colimits in comma categories
We build limits in the comma category `Comma L R` provided that the two source categories have
limits and `R` preserves them.
This is used to construct limits in the arrow category, structured arrow category and under
category, and show that the appropriate forgetful functors create limits.
The duals of all the above are also given.
-/
@[expose] public section
namespace CategoryTheory
open Category Limits Functor
universe w' w v₁ v₂ v₃ u₁ u₂ u₃
variable {J : Type w} [Category.{w'} J]
variable {A : Type u₁} [Category.{v₁} A]
variable {B : Type u₂} [Category.{v₂} B]
variable {T : Type u₃} [Category.{v₃} T]
namespace Comma
variable {L : A ⥤ T} {R : B ⥤ T}
variable (F : J ⥤ Comma L R)
/-- (Implementation). An auxiliary cone which is useful in order to construct limits
in the comma category. -/
@[simps!]
def limitAuxiliaryCone (c₁ : Cone (F ⋙ fst L R)) : Cone ((F ⋙ snd L R) ⋙ R) :=
(Cone.postcompose (whiskerLeft F (Comma.natTrans L R) :)).obj (L.mapCone c₁)
/-- If `R` preserves the appropriate limit, then given a cone for `F ⋙ fst L R : J ⥤ L` and a
limit cone for `F ⋙ snd L R : J ⥤ R` we can build a cone for `F` which will turn out to be a limit
cone.
-/
@[simps]
noncomputable def coneOfPreserves [PreservesLimit (F ⋙ snd L R) R] (c₁ : Cone (F ⋙ fst L R))
{c₂ : Cone (F ⋙ snd L R)} (t₂ : IsLimit c₂) : Cone F where
pt :=
{ left := c₁.pt
right := c₂.pt
hom := (isLimitOfPreserves R t₂).lift (limitAuxiliaryCone _ c₁) }
π :=
{ app := fun j =>
{ left := c₁.π.app j
right := c₂.π.app j
w := ((isLimitOfPreserves R t₂).fac (limitAuxiliaryCone F c₁) j).symm }
naturality := fun j₁ j₂ t => by
ext
· simp [← c₁.w t]
· simp [← c₂.w t] }
set_option backward.isDefEq.respectTransparency false in
/-- Provided that `R` preserves the appropriate limit, then the cone in `coneOfPreserves` is a
limit. -/
noncomputable def coneOfPreservesIsLimit [PreservesLimit (F ⋙ snd L R) R] {c₁ : Cone (F ⋙ fst L R)}
(t₁ : IsLimit c₁) {c₂ : Cone (F ⋙ snd L R)} (t₂ : IsLimit c₂) :
IsLimit (coneOfPreserves F c₁ t₂) where
lift s :=
{ left := t₁.lift ((fst L R).mapCone s)
right := t₂.lift ((snd L R).mapCone s)
w :=
(isLimitOfPreserves R t₂).hom_ext fun j => by
rw [coneOfPreserves_pt_hom, assoc, assoc, (isLimitOfPreserves R t₂).fac,
limitAuxiliaryCone_π_app, ← L.map_comp_assoc, t₁.fac, R.mapCone_π_app,
← R.map_comp, t₂.fac]
exact (s.π.app j).w }
uniq s m w := by
apply CommaMorphism.ext
· exact t₁.uniq ((fst L R).mapCone s) _ (fun j => by simp [← w])
· exact t₂.uniq ((snd L R).mapCone s) _ (fun j => by simp [← w])
/-- (Implementation). An auxiliary cocone which is useful in order to construct colimits
in the comma category. -/
@[simps!]
def colimitAuxiliaryCocone (c₂ : Cocone (F ⋙ snd L R)) : Cocone ((F ⋙ fst L R) ⋙ L) :=
(Cocone.precompose (whiskerLeft F (Comma.natTrans L R) :)).obj (R.mapCocone c₂)
/--
If `L` preserves the appropriate colimit, then given a colimit cocone for `F ⋙ fst L R : J ⥤ L` and
a cocone for `F ⋙ snd L R : J ⥤ R` we can build a cocone for `F` which will turn out to be a
colimit cocone.
-/
@[simps]
noncomputable def coconeOfPreserves [PreservesColimit (F ⋙ fst L R) L] {c₁ : Cocone (F ⋙ fst L R)}
(t₁ : IsColimit c₁) (c₂ : Cocone (F ⋙ snd L R)) : Cocone F where
pt :=
{ left := c₁.pt
right := c₂.pt
hom := (isColimitOfPreserves L t₁).desc (colimitAuxiliaryCocone _ c₂) }
ι :=
{ app := fun j =>
{ left := c₁.ι.app j
right := c₂.ι.app j
w := (isColimitOfPreserves L t₁).fac (colimitAuxiliaryCocone _ c₂) j }
naturality := fun j₁ j₂ t => by
ext
· simp [← c₁.w t]
· simp [← c₂.w t] }
set_option backward.isDefEq.respectTransparency false in
/-- Provided that `L` preserves the appropriate colimit, then the cocone in `coconeOfPreserves` is
a colimit. -/
noncomputable def coconeOfPreservesIsColimit [PreservesColimit (F ⋙ fst L R) L]
{c₁ : Cocone (F ⋙ fst L R)}
(t₁ : IsColimit c₁) {c₂ : Cocone (F ⋙ snd L R)} (t₂ : IsColimit c₂) :
IsColimit (coconeOfPreserves F t₁ c₂) where
desc s :=
{ left := t₁.desc ((fst L R).mapCocone s)
right := t₂.desc ((snd L R).mapCocone s)
w :=
(isColimitOfPreserves L t₁).hom_ext fun j => by
rw [coconeOfPreserves_pt_hom, (isColimitOfPreserves L t₁).fac_assoc,
colimitAuxiliaryCocone_ι_app, assoc, ← R.map_comp, t₂.fac, L.mapCocone_ι_app, ←
L.map_comp_assoc, t₁.fac]
exact (s.ι.app j).w }
uniq s m w := by
apply CommaMorphism.ext
· exact t₁.uniq ((fst L R).mapCocone s) _ (fun j => by simp [← w])
· exact t₂.uniq ((snd L R).mapCocone s) _ (fun j => by simp [← w])
instance hasLimit (F : J ⥤ Comma L R) [HasLimit (F ⋙ fst L R)] [HasLimit (F ⋙ snd L R)]
[PreservesLimit (F ⋙ snd L R) R] : HasLimit F :=
HasLimit.mk ⟨_, coneOfPreservesIsLimit _ (limit.isLimit _) (limit.isLimit _)⟩
instance hasLimitsOfShape [HasLimitsOfShape J A] [HasLimitsOfShape J B]
[PreservesLimitsOfShape J R] : HasLimitsOfShape J (Comma L R) where
instance hasLimitsOfSize [HasLimitsOfSize.{w, w'} A] [HasLimitsOfSize.{w, w'} B]
[PreservesLimitsOfSize.{w, w'} R] : HasLimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
instance hasColimit (F : J ⥤ Comma L R) [HasColimit (F ⋙ fst L R)] [HasColimit (F ⋙ snd L R)]
[PreservesColimit (F ⋙ fst L R) L] : HasColimit F :=
HasColimit.mk ⟨_, coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _)⟩
instance hasColimitsOfShape [HasColimitsOfShape J A] [HasColimitsOfShape J B]
[PreservesColimitsOfShape J L] : HasColimitsOfShape J (Comma L R) where
instance hasColimitsOfSize [HasColimitsOfSize.{w, w'} A] [HasColimitsOfSize.{w, w'} B]
[PreservesColimitsOfSize.{w, w'} L] : HasColimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
instance preservesColimitsOfShape_fst [HasColimitsOfShape J A] [HasColimitsOfShape J B]
[PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.fst L R) where
preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
(coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
(colimit.isColimit _)
instance preservesColimitsOfShape_snd [HasColimitsOfShape J A] [HasColimitsOfShape J B]
[PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.snd L R) where
preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
(coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
(colimit.isColimit _)
end Comma
namespace Arrow
set_option backward.isDefEq.respectTransparency false in
instance hasLimit (F : J ⥤ Arrow T) [i₁ : HasLimit (F ⋙ leftFunc)] [i₂ : HasLimit (F ⋙ rightFunc)] :
HasLimit F := by
haveI : HasLimit (F ⋙ Comma.fst _ _) := i₁
haveI : HasLimit (F ⋙ Comma.snd _ _) := i₂
apply Comma.hasLimit
instance hasLimitsOfShape [HasLimitsOfShape J T] : HasLimitsOfShape J (Arrow T) where
instance hasLimits [HasLimits T] : HasLimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩
set_option backward.isDefEq.respectTransparency false in
instance hasColimit (F : J ⥤ Arrow T) [i₁ : HasColimit (F ⋙ leftFunc)]
[i₂ : HasColimit (F ⋙ rightFunc)] : HasColimit F := by
haveI : HasColimit (F ⋙ Comma.fst _ _) := i₁
haveI : HasColimit (F ⋙ Comma.snd _ _) := i₂
apply Comma.hasColimit
instance hasColimitsOfShape [HasColimitsOfShape J T] : HasColimitsOfShape J (Arrow T) where
instance hasColimits [HasColimits T] : HasColimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩
instance preservesColimitsOfShape_leftFunc [HasColimitsOfShape J T] :
PreservesColimitsOfShape J (Arrow.leftFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_fst
instance preservesColimitsOfShape_rightFunc [HasColimitsOfShape J T] :
PreservesColimitsOfShape J (Arrow.rightFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_snd
end Arrow
namespace StructuredArrow
variable {X : T} {G : A ⥤ T} (F : J ⥤ StructuredArrow X G)
instance [G.Faithful] [G.Full] {Y : A} : HasInitial (StructuredArrow (G.obj Y) G) :=
StructuredArrow.mkIdInitial.hasInitial
set_option backward.isDefEq.respectTransparency false in
instance hasLimit [i₁ : HasLimit (F ⋙ proj X G)] [i₂ : PreservesLimit (F ⋙ proj X G) G] :
HasLimit F := by
haveI : HasLimit (F ⋙ Comma.snd (Functor.fromPUnit X) G) := i₁
haveI : PreservesLimit (F ⋙ Comma.snd (Functor.fromPUnit X) G) _ := i₂
apply Comma.hasLimit
instance hasLimitsOfShape [HasLimitsOfShape J A] [PreservesLimitsOfShape J G] :
HasLimitsOfShape J (StructuredArrow X G) where
instance hasLimitsOfSize [HasLimitsOfSize.{w, w'} A] [PreservesLimitsOfSize.{w, w'} G] :
HasLimitsOfSize.{w, w'} (StructuredArrow X G) :=
⟨fun J hJ => by infer_instance⟩
set_option backward.isDefEq.respectTransparency false in
noncomputable instance createsLimit [i : PreservesLimit (F ⋙ proj X G) G] :
CreatesLimit F (proj X G) :=
letI : PreservesLimit (F ⋙ Comma.snd (Functor.fromPUnit X) G) G := i
createsLimitOfReflectsIso fun _ t =>
{ liftedCone := Comma.coneOfPreserves F punitCone t
makesLimit := Comma.coneOfPreservesIsLimit _ punitConeIsLimit _
validLift := Cone.ext (Iso.refl _) fun _ => (id_comp _).symm }
noncomputable instance createsLimitsOfShape [PreservesLimitsOfShape J G] :
CreatesLimitsOfShape J (proj X G) where
noncomputable instance createsLimitsOfSize [PreservesLimitsOfSize.{w, w'} G] :
CreatesLimitsOfSize.{w, w'} (proj X G :) where
instance mono_right_of_mono [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
{Y Z : StructuredArrow X G} (f : Y ⟶ Z) [Mono f] : Mono f.right :=
show Mono ((proj X G).map f) from inferInstance
theorem mono_iff_mono_right [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
{Y Z : StructuredArrow X G} (f : Y ⟶ Z) : Mono f ↔ Mono f.right :=
⟨fun _ => inferInstance, fun _ => mono_of_mono_right f⟩
end StructuredArrow
namespace CostructuredArrow
variable {G : A ⥤ T} {X : T} (F : J ⥤ CostructuredArrow G X)
instance hasTerminal [G.Faithful] [G.Full] {Y : A} :
HasTerminal (CostructuredArrow G (G.obj Y)) :=
CostructuredArrow.mkIdTerminal.hasTerminal
set_option backward.isDefEq.respectTransparency false in
instance hasColimit [i₁ : HasColimit (F ⋙ proj G X)] [i₂ : PreservesColimit (F ⋙ proj G X) G] :
HasColimit F := by
haveI : HasColimit (F ⋙ Comma.fst G (Functor.fromPUnit X)) := i₁
haveI : PreservesColimit (F ⋙ Comma.fst G (Functor.fromPUnit X)) _ := i₂
apply Comma.hasColimit
instance hasColimitsOfShape [HasColimitsOfShape J A] [PreservesColimitsOfShape J G] :
HasColimitsOfShape J (CostructuredArrow G X) where
instance hasColimitsOfSize [HasColimitsOfSize.{w, w'} A] [PreservesColimitsOfSize.{w, w'} G] :
HasColimitsOfSize.{w, w'} (CostructuredArrow G X) :=
⟨fun _ _ => inferInstance⟩
set_option backward.isDefEq.respectTransparency false in
noncomputable instance createsColimit [i : PreservesColimit (F ⋙ proj G X) G] :
CreatesColimit F (proj G X) :=
letI : PreservesColimit (F ⋙ Comma.fst G (Functor.fromPUnit X)) G := i
createsColimitOfReflectsIso fun _ t =>
{ liftedCocone := Comma.coconeOfPreserves F t punitCocone
makesColimit := Comma.coconeOfPreservesIsColimit _ _ punitCoconeIsColimit
validLift := Cocone.ext (Iso.refl _) fun _ => comp_id _ }
noncomputable instance createsColimitsOfShape [PreservesColimitsOfShape J G] :
CreatesColimitsOfShape J (proj G X) where
noncomputable instance createsColimitsOfSize [PreservesColimitsOfSize.{w, w'} G] :
CreatesColimitsOfSize.{w, w'} (proj G X :) where
instance epi_left_of_epi [HasPushouts A] [PreservesColimitsOfShape WalkingSpan G]
{Y Z : CostructuredArrow G X} (f : Y ⟶ Z) [Epi f] : Epi f.left :=
show Epi ((proj G X).map f) from inferInstance
theorem epi_iff_epi_left [HasPushouts A] [PreservesColimitsOfShape WalkingSpan G]
{Y Z : CostructuredArrow G X} (f : Y ⟶ Z) : Epi f ↔ Epi f.left :=
⟨fun _ => inferInstance, fun _ => epi_of_epi_left f⟩
end CostructuredArrow
namespace Over
instance {X : T} : HasTerminal (Over X) := CostructuredArrow.hasTerminal
end Over
namespace Under
instance {X : T} : HasInitial (Under X) := Under.mkIdInitial.hasInitial
end Under
end CategoryTheory