-
Notifications
You must be signed in to change notification settings - Fork 384
/
Copy pathFlat.lean
336 lines (287 loc) · 15.3 KB
/
Flat.lean
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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
/-
Copyright (c) 2021 Andrew Yang. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Andrew Yang
-/
import Mathlib.CategoryTheory.Limits.ConeCategory
import Mathlib.CategoryTheory.Limits.FilteredColimitCommutesFiniteLimit
import Mathlib.CategoryTheory.Limits.Preserves.Filtered
import Mathlib.CategoryTheory.Limits.Preserves.FunctorCategory
import Mathlib.CategoryTheory.Limits.Bicones
import Mathlib.CategoryTheory.Limits.Comma
import Mathlib.CategoryTheory.Limits.Preserves.Finite
import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits
#align_import category_theory.functor.flat from "leanprover-community/mathlib"@"39478763114722f0ec7613cb2f3f7701f9b86c8d"
/-!
# Representably flat functors
We define representably flat functors as functors such that the category of structured arrows
over `X` is cofiltered for each `X`. This concept is also known as flat functors as in [Elephant]
Remark C2.3.7, and this name is suggested by Mike Shulman in
https://golem.ph.utexas.edu/category/2011/06/flat_functors_and_morphisms_of.html to avoid
confusion with other notions of flatness.
This definition is equivalent to left exact functors (functors that preserves finite limits) when
`C` has all finite limits.
## Main results
* `flat_of_preservesFiniteLimits`: If `F : C ⥤ D` preserves finite limits and `C` has all finite
limits, then `F` is flat.
* `preservesFiniteLimitsOfFlat`: If `F : C ⥤ D` is flat, then it preserves all finite limits.
* `preservesFiniteLimitsIffFlat`: If `C` has all finite limits,
then `F` is flat iff `F` is left_exact.
* `lanPreservesFiniteLimitsOfFlat`: If `F : C ⥤ D` is a flat functor between small categories,
then the functor `Lan F.op` between presheaves of sets preserves all finite limits.
* `flat_iff_lan_flat`: If `C`, `D` are small and `C` has all finite limits, then `F` is flat iff
`Lan F.op : (Cᵒᵖ ⥤ Type*) ⥤ (Dᵒᵖ ⥤ Type*)` is flat.
* `preservesFiniteLimitsIffLanPreservesFiniteLimits`: If `C`, `D` are small and `C` has all
finite limits, then `F` preserves finite limits iff `Lan F.op : (Cᵒᵖ ⥤ Type*) ⥤ (Dᵒᵖ ⥤ Type*)`
does.
-/
universe w v₁ v₂ v₃ u₁ u₂ u₃
open CategoryTheory
open CategoryTheory.Limits
open Opposite
namespace CategoryTheory
section RepresentablyFlat
variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D]
variable {E : Type u₃} [Category.{v₃} E]
/-- A functor `F : C ⥤ D` is representably-flat functor if the comma category `(X/F)`
is cofiltered for each `X : C`.
-/
class RepresentablyFlat (F : C ⥤ D) : Prop where
cofiltered : ∀ X : D, IsCofiltered (StructuredArrow X F)
#align category_theory.representably_flat CategoryTheory.RepresentablyFlat
attribute [instance] RepresentablyFlat.cofiltered
instance RepresentablyFlat.of_isRightAdjoint (F : C ⥤ D) [F.IsRightAdjoint] :
RepresentablyFlat F where
cofiltered _ := IsCofiltered.of_isInitial _ (mkInitialOfLeftAdjoint _ (.ofIsRightAdjoint F) _)
theorem RepresentablyFlat.id : RepresentablyFlat (𝟭 C) := inferInstance
#align category_theory.representably_flat.id CategoryTheory.RepresentablyFlat.id
instance RepresentablyFlat.comp (F : C ⥤ D) (G : D ⥤ E) [RepresentablyFlat F]
[RepresentablyFlat G] : RepresentablyFlat (F ⋙ G) := by
refine ⟨fun X => IsCofiltered.of_cone_nonempty.{0} _ (fun {J} _ _ H => ?_)⟩
obtain ⟨c₁⟩ := IsCofiltered.cone_nonempty (H ⋙ StructuredArrow.pre X F G)
let H₂ : J ⥤ StructuredArrow c₁.pt.right F :=
{ obj := fun j => StructuredArrow.mk (c₁.π.app j).right
map := fun {j j'} f =>
StructuredArrow.homMk (H.map f).right (congrArg CommaMorphism.right (c₁.w f)) }
obtain ⟨c₂⟩ := IsCofiltered.cone_nonempty H₂
exact ⟨⟨StructuredArrow.mk (c₁.pt.hom ≫ G.map c₂.pt.hom),
⟨fun j => StructuredArrow.homMk (c₂.π.app j).right (by simp [← G.map_comp, (c₂.π.app j).w]),
fun j j' f => by simpa using (c₂.w f).symm⟩⟩⟩
#align category_theory.representably_flat.comp CategoryTheory.RepresentablyFlat.comp
end RepresentablyFlat
section HasLimit
variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D]
theorem flat_of_preservesFiniteLimits [HasFiniteLimits C] (F : C ⥤ D) [PreservesFiniteLimits F] :
RepresentablyFlat F :=
⟨fun X =>
haveI : HasFiniteLimits (StructuredArrow X F) := by
apply hasFiniteLimits_of_hasFiniteLimits_of_size.{v₁} (StructuredArrow X F)
intro J sJ fJ
constructor
-- Porting note: instance was inferred automatically in Lean 3
infer_instance
IsCofiltered.of_hasFiniteLimits _⟩
#align category_theory.flat_of_preserves_finite_limits CategoryTheory.flat_of_preservesFiniteLimits
namespace PreservesFiniteLimitsOfFlat
open StructuredArrow
variable {J : Type v₁} [SmallCategory J] [FinCategory J] {K : J ⥤ C}
variable (F : C ⥤ D) [RepresentablyFlat F] {c : Cone K} (hc : IsLimit c) (s : Cone (K ⋙ F))
/-- (Implementation).
Given a limit cone `c : cone K` and a cone `s : cone (K ⋙ F)` with `F` representably flat,
`s` can factor through `F.map_cone c`.
-/
noncomputable def lift : s.pt ⟶ F.obj c.pt :=
let s' := IsCofiltered.cone (s.toStructuredArrow ⋙ StructuredArrow.pre _ K F)
s'.pt.hom ≫
(F.map <|
hc.lift <|
(Cones.postcompose
({ app := fun X => 𝟙 _ } :
(s.toStructuredArrow ⋙ pre s.pt K F) ⋙ proj s.pt F ⟶ K)).obj <|
(StructuredArrow.proj s.pt F).mapCone s')
#align category_theory.preserves_finite_limits_of_flat.lift CategoryTheory.PreservesFiniteLimitsOfFlat.lift
theorem fac (x : J) : lift F hc s ≫ (F.mapCone c).π.app x = s.π.app x := by
simp [lift, ← Functor.map_comp]
#align category_theory.preserves_finite_limits_of_flat.fac CategoryTheory.PreservesFiniteLimitsOfFlat.fac
theorem uniq {K : J ⥤ C} {c : Cone K} (hc : IsLimit c) (s : Cone (K ⋙ F))
(f₁ f₂ : s.pt ⟶ F.obj c.pt) (h₁ : ∀ j : J, f₁ ≫ (F.mapCone c).π.app j = s.π.app j)
(h₂ : ∀ j : J, f₂ ≫ (F.mapCone c).π.app j = s.π.app j) : f₁ = f₂ := by
-- We can make two cones over the diagram of `s` via `f₁` and `f₂`.
let α₁ : (F.mapCone c).toStructuredArrow ⋙ map f₁ ⟶ s.toStructuredArrow :=
{ app := fun X => eqToHom (by simp [← h₁]) }
let α₂ : (F.mapCone c).toStructuredArrow ⋙ map f₂ ⟶ s.toStructuredArrow :=
{ app := fun X => eqToHom (by simp [← h₂]) }
let c₁ : Cone (s.toStructuredArrow ⋙ pre s.pt K F) :=
(Cones.postcompose (whiskerRight α₁ (pre s.pt K F) : _)).obj (c.toStructuredArrowCone F f₁)
let c₂ : Cone (s.toStructuredArrow ⋙ pre s.pt K F) :=
(Cones.postcompose (whiskerRight α₂ (pre s.pt K F) : _)).obj (c.toStructuredArrowCone F f₂)
-- The two cones can then be combined and we may obtain a cone over the two cones since
-- `StructuredArrow s.pt F` is cofiltered.
let c₀ := IsCofiltered.cone (biconeMk _ c₁ c₂)
let g₁ : c₀.pt ⟶ c₁.pt := c₀.π.app Bicone.left
let g₂ : c₀.pt ⟶ c₂.pt := c₀.π.app Bicone.right
-- Then `g₁.right` and `g₂.right` are two maps from the same cone into the `c`.
have : ∀ j : J, g₁.right ≫ c.π.app j = g₂.right ≫ c.π.app j := by
intro j
injection c₀.π.naturality (BiconeHom.left j) with _ e₁
injection c₀.π.naturality (BiconeHom.right j) with _ e₂
convert e₁.symm.trans e₂ <;> simp [c₁, c₂]
have : c.extend g₁.right = c.extend g₂.right := by
unfold Cone.extend
congr 1
ext x
apply this
-- And thus they are equal as `c` is the limit.
have : g₁.right = g₂.right := calc
g₁.right = hc.lift (c.extend g₁.right) := by
apply hc.uniq (c.extend _)
-- Porting note: was `by tidy`, but `aesop` only works if max heartbeats
-- is increased, so we replace it by the output of `tidy?`
intro j; rfl
_ = hc.lift (c.extend g₂.right) := by
congr
_ = g₂.right := by
symm
apply hc.uniq (c.extend _)
-- Porting note: was `by tidy`, but `aesop` only works if max heartbeats
-- is increased, so we replace it by the output of `tidy?`
intro _; rfl
-- Finally, since `fᵢ` factors through `F(gᵢ)`, the result follows.
calc
f₁ = 𝟙 _ ≫ f₁ := by simp
_ = c₀.pt.hom ≫ F.map g₁.right := g₁.w
_ = c₀.pt.hom ≫ F.map g₂.right := by rw [this]
_ = 𝟙 _ ≫ f₂ := g₂.w.symm
_ = f₂ := by simp
#align category_theory.preserves_finite_limits_of_flat.uniq CategoryTheory.PreservesFiniteLimitsOfFlat.uniq
end PreservesFiniteLimitsOfFlat
/-- Representably flat functors preserve finite limits. -/
noncomputable def preservesFiniteLimitsOfFlat (F : C ⥤ D) [RepresentablyFlat F] :
PreservesFiniteLimits F := by
apply preservesFiniteLimitsOfPreservesFiniteLimitsOfSize
intro J _ _; constructor
intro K; constructor
intro c hc
exact
{ lift := PreservesFiniteLimitsOfFlat.lift F hc
fac := PreservesFiniteLimitsOfFlat.fac F hc
uniq := fun s m h => by
apply PreservesFiniteLimitsOfFlat.uniq F hc
· exact h
· exact PreservesFiniteLimitsOfFlat.fac F hc s }
#align category_theory.preserves_finite_limits_of_flat CategoryTheory.preservesFiniteLimitsOfFlat
/-- If `C` is finitely cocomplete, then `F : C ⥤ D` is representably flat iff it preserves
finite limits.
-/
noncomputable def preservesFiniteLimitsIffFlat [HasFiniteLimits C] (F : C ⥤ D) :
RepresentablyFlat F ≃ PreservesFiniteLimits F where
toFun _ := preservesFiniteLimitsOfFlat F
invFun _ := flat_of_preservesFiniteLimits F
left_inv _ := proof_irrel _ _
right_inv x := by
cases x
unfold preservesFiniteLimitsOfFlat
dsimp only [preservesFiniteLimitsOfPreservesFiniteLimitsOfSize]
congr
-- Porting note: this next line wasn't needed in lean 3
subsingleton
#align category_theory.preserves_finite_limits_iff_flat CategoryTheory.preservesFiniteLimitsIffFlat
end HasLimit
section SmallCategory
variable {C D : Type u₁} [SmallCategory C] [SmallCategory D] (E : Type u₂) [Category.{u₁} E]
/-- (Implementation)
The evaluation of `Lan F` at `X` is the colimit over the costructured arrows over `X`.
-/
noncomputable def lanEvaluationIsoColim (F : C ⥤ D) (X : D)
[∀ X : D, HasColimitsOfShape (CostructuredArrow F X) E] :
lan F ⋙ (evaluation D E).obj X ≅
(whiskeringLeft _ _ E).obj (CostructuredArrow.proj F X) ⋙ colim :=
NatIso.ofComponents (fun G => colim.mapIso (Iso.refl _))
(by
intro G H i
-- Porting note (#11041): was `ext` in lean 3
-- Now `ext` can't see that `lan` is a colimit.
-- Uncertain whether it makes sense to add another `@[ext]` lemma.
apply colimit.hom_ext
intro j
simp only [Functor.comp_map, Functor.mapIso_refl, evaluation_obj_map, whiskeringLeft_obj_map,
lan_map_app, colimit.ι_desc_assoc, Category.comp_id, Category.assoc]
-- Porting note (#11041): this deals with the fact that the type of `lan_map_app` has changed
erw [show ((Lan.equiv F H (Lan.loc F H)) (𝟙 (Lan.loc F H))).app j.left =
colimit.ι (Lan.diagram F H (F.obj j.left))
(CostructuredArrow.mk (𝟙 (F.obj j.left))) by apply Category.comp_id]
erw [colimit.ι_pre_assoc (Lan.diagram F H X) (CostructuredArrow.map j.hom), Category.id_comp,
Category.comp_id, colimit.ι_map]
rcases j with ⟨j_left, ⟨⟨⟩⟩, j_hom⟩
congr
rw [CostructuredArrow.map_mk, Category.id_comp, CostructuredArrow.mk])
set_option linter.uppercaseLean3 false in
#align category_theory.Lan_evaluation_iso_colim CategoryTheory.lanEvaluationIsoColim
variable [ConcreteCategory.{u₁} E] [HasLimits E] [HasColimits E]
variable [ReflectsLimits (forget E)] [PreservesFilteredColimits (forget E)]
variable [PreservesLimits (forget E)]
/-- If `F : C ⥤ D` is a representably flat functor between small categories, then the functor
`Lan F.op` that takes presheaves over `C` to presheaves over `D` preserves finite limits.
-/
noncomputable instance lanPreservesFiniteLimitsOfFlat (F : C ⥤ D) [RepresentablyFlat F] :
PreservesFiniteLimits (lan F.op : _ ⥤ Dᵒᵖ ⥤ E) := by
apply preservesFiniteLimitsOfPreservesFiniteLimitsOfSize.{u₁}
intro J _ _
apply preservesLimitsOfShapeOfEvaluation (lan F.op : (Cᵒᵖ ⥤ E) ⥤ Dᵒᵖ ⥤ E) J
intro K
haveI : IsFiltered (CostructuredArrow F.op K) :=
IsFiltered.of_equivalence (structuredArrowOpEquivalence F (unop K))
exact preservesLimitsOfShapeOfNatIso (lanEvaluationIsoColim _ _ _).symm
set_option linter.uppercaseLean3 false in
#align category_theory.Lan_preserves_finite_limits_of_flat CategoryTheory.lanPreservesFiniteLimitsOfFlat
instance lan_flat_of_flat (F : C ⥤ D) [RepresentablyFlat F] :
RepresentablyFlat (lan F.op : _ ⥤ Dᵒᵖ ⥤ E) :=
flat_of_preservesFiniteLimits _
set_option linter.uppercaseLean3 false in
#align category_theory.Lan_flat_of_flat CategoryTheory.lan_flat_of_flat
variable [HasFiniteLimits C]
noncomputable instance lanPreservesFiniteLimitsOfPreservesFiniteLimits (F : C ⥤ D)
[PreservesFiniteLimits F] : PreservesFiniteLimits (lan F.op : _ ⥤ Dᵒᵖ ⥤ E) := by
haveI := flat_of_preservesFiniteLimits F
infer_instance
set_option linter.uppercaseLean3 false in
#align category_theory.Lan_preserves_finite_limits_of_preserves_finite_limits CategoryTheory.lanPreservesFiniteLimitsOfPreservesFiniteLimits
theorem flat_iff_lan_flat (F : C ⥤ D) :
RepresentablyFlat F ↔ RepresentablyFlat (lan F.op : _ ⥤ Dᵒᵖ ⥤ Type u₁) :=
⟨fun H => inferInstance, fun H => by
haveI := preservesFiniteLimitsOfFlat (lan F.op : _ ⥤ Dᵒᵖ ⥤ Type u₁)
haveI : PreservesFiniteLimits F := by
apply preservesFiniteLimitsOfPreservesFiniteLimitsOfSize.{u₁}
intros; apply preservesLimitOfLanPreservesLimit
apply flat_of_preservesFiniteLimits⟩
set_option linter.uppercaseLean3 false in
#align category_theory.flat_iff_Lan_flat CategoryTheory.flat_iff_lan_flat
/-- If `C` is finitely complete, then `F : C ⥤ D` preserves finite limits iff
`Lan F.op : (Cᵒᵖ ⥤ Type*) ⥤ (Dᵒᵖ ⥤ Type*)` preserves finite limits.
-/
noncomputable def preservesFiniteLimitsIffLanPreservesFiniteLimits (F : C ⥤ D) :
PreservesFiniteLimits F ≃ PreservesFiniteLimits (lan F.op : _ ⥤ Dᵒᵖ ⥤ Type u₁) where
toFun _ := inferInstance
invFun _ := by
apply preservesFiniteLimitsOfPreservesFiniteLimitsOfSize.{u₁}
intros; apply preservesLimitOfLanPreservesLimit
left_inv x := by
-- Porting note: `cases x` and an `unfold` not necessary in lean 4.
-- Remark : in mathlib3 we had `unfold preservesFiniteLimitsOfFlat`
-- but there was no `preservesFiniteLimitsOfFlat` in the goal! Experimentation
-- indicates that it was doing the same as `dsimp only`
dsimp only [preservesFiniteLimitsOfPreservesFiniteLimitsOfSize]; congr
-- Porting note: next line wasn't necessary in lean 3
subsingleton
right_inv x := by
-- cases x; -- Porting note: not necessary in lean 4
dsimp only [lanPreservesFiniteLimitsOfPreservesFiniteLimits,
lanPreservesFiniteLimitsOfFlat,
preservesFiniteLimitsOfPreservesFiniteLimitsOfSize]
congr
-- Porting note: next line wasn't necessary in lean 3
subsingleton
set_option linter.uppercaseLean3 false in
#align category_theory.preserves_finite_limits_iff_Lan_preserves_finite_limits CategoryTheory.preservesFiniteLimitsIffLanPreservesFiniteLimits
end SmallCategory
end CategoryTheory