Skip to content

Commit e76b292

Browse files
committed
feat(CategoryTheory/Functor): more API for pointwise Kan extensions (#22474)
Transport pointwise Kan extensions via isomorphisms/equivalences.
1 parent 23d677e commit e76b292

File tree

4 files changed

+157
-7
lines changed

4 files changed

+157
-7
lines changed

Mathlib/CategoryTheory/Functor/KanExtension/Pointwise.lean

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ open Category Limits
3333

3434
namespace Functor
3535

36-
variable {C D H : Type*} [Category C] [Category D] [Category H] (L : C ⥤ D) (F : C ⥤ H)
36+
variable {C D D' H : Type*} [Category C] [Category D] [Category D'] [Category H]
37+
(L : C ⥤ D) (L' : C ⥤ D') (F : C ⥤ H)
3738

3839
/-- The condition that a functor `F` has a pointwise left Kan extension along `L` at `Y`.
3940
It means that the functor `CostructuredArrow.proj L Y ⋙ F : CostructuredArrow L Y ⥤ H`
@@ -55,6 +56,108 @@ abbrev HasPointwiseRightKanExtensionAt (Y : D) :=
5556
that it has a pointwise right Kan extension at any object. -/
5657
abbrev HasPointwiseRightKanExtension := ∀ (Y : D), HasPointwiseRightKanExtensionAt L F Y
5758

59+
lemma hasPointwiseLeftKanExtensionAt_iff_of_iso {Y₁ Y₂ : D} (e : Y₁ ≅ Y₂) :
60+
HasPointwiseLeftKanExtensionAt L F Y₁ ↔
61+
HasPointwiseLeftKanExtensionAt L F Y₂ := by
62+
revert Y₁ Y₂ e
63+
suffices ∀ ⦃Y₁ Y₂ : D⦄ (_ : Y₁ ≅ Y₂) [HasPointwiseLeftKanExtensionAt L F Y₁],
64+
HasPointwiseLeftKanExtensionAt L F Y₂ from
65+
fun Y₁ Y₂ e => ⟨fun _ => this e, fun _ => this e.symm⟩
66+
intro Y₁ Y₂ e _
67+
change HasColimit ((CostructuredArrow.mapIso e.symm).functor ⋙ CostructuredArrow.proj L Y₁ ⋙ F)
68+
infer_instance
69+
70+
lemma hasPointwiseRightKanExtensionAt_iff_of_iso {Y₁ Y₂ : D} (e : Y₁ ≅ Y₂) :
71+
HasPointwiseRightKanExtensionAt L F Y₁ ↔
72+
HasPointwiseRightKanExtensionAt L F Y₂ := by
73+
revert Y₁ Y₂ e
74+
suffices ∀ ⦃Y₁ Y₂ : D⦄ (_ : Y₁ ≅ Y₂) [HasPointwiseRightKanExtensionAt L F Y₁],
75+
HasPointwiseRightKanExtensionAt L F Y₂ from
76+
fun Y₁ Y₂ e => ⟨fun _ => this e, fun _ => this e.symm⟩
77+
intro Y₁ Y₂ e _
78+
change HasLimit ((StructuredArrow.mapIso e.symm).functor ⋙ StructuredArrow.proj Y₁ L ⋙ F)
79+
infer_instance
80+
81+
variable {L} in
82+
/-- `HasPointwiseLeftKanExtensionAt` is invariant when we replace `L` by an equivalent functor. -/
83+
lemma hasPointwiseLeftKanExtensionAt_iff_of_natIso {L' : C ⥤ D} (e : L ≅ L') (Y : D) :
84+
HasPointwiseLeftKanExtensionAt L F Y ↔
85+
HasPointwiseLeftKanExtensionAt L' F Y := by
86+
revert L L' e
87+
suffices ∀ ⦃L L' : C ⥤ D⦄ (_ : L ≅ L') [HasPointwiseLeftKanExtensionAt L F Y],
88+
HasPointwiseLeftKanExtensionAt L' F Y from
89+
fun L L' e => ⟨fun _ => this e, fun _ => this e.symm⟩
90+
intro L L' e _
91+
let Φ : CostructuredArrow L' Y ≌ CostructuredArrow L Y := Comma.mapLeftIso _ e.symm
92+
let e' : CostructuredArrow.proj L' Y ⋙ F ≅
93+
Φ.functor ⋙ CostructuredArrow.proj L Y ⋙ F := Iso.refl _
94+
exact hasColimit_of_iso e'
95+
96+
variable {L} in
97+
/-- `HasPointwiseRightKanExtensionAt` is invariant when we replace `L` by an equivalent functor. -/
98+
lemma hasPointwiseRightKanExtensionAt_iff_of_natIso {L' : C ⥤ D} (e : L ≅ L') (Y : D) :
99+
HasPointwiseRightKanExtensionAt L F Y ↔
100+
HasPointwiseRightKanExtensionAt L' F Y := by
101+
revert L L' e
102+
suffices ∀ ⦃L L' : C ⥤ D⦄ (_ : L ≅ L') [HasPointwiseRightKanExtensionAt L F Y],
103+
HasPointwiseRightKanExtensionAt L' F Y from
104+
fun L L' e => ⟨fun _ => this e, fun _ => this e.symm⟩
105+
intro L L' e _
106+
let Φ : StructuredArrow Y L' ≌ StructuredArrow Y L := Comma.mapRightIso _ e.symm
107+
let e' : StructuredArrow.proj Y L' ⋙ F ≅
108+
Φ.functor ⋙ StructuredArrow.proj Y L ⋙ F := Iso.refl _
109+
exact hasLimit_of_iso e'.symm
110+
111+
lemma hasPointwiseLeftKanExtensionAt_of_equivalence
112+
(E : D ≌ D') (eL : L ⋙ E.functor ≅ L') (Y : D) (Y' : D') (e : E.functor.obj Y ≅ Y')
113+
[HasPointwiseLeftKanExtensionAt L F Y] :
114+
HasPointwiseLeftKanExtensionAt L' F Y' := by
115+
rw [← hasPointwiseLeftKanExtensionAt_iff_of_natIso F eL,
116+
hasPointwiseLeftKanExtensionAt_iff_of_iso _ F e.symm]
117+
let Φ := CostructuredArrow.post L E.functor Y
118+
have : HasColimit ((asEquivalence Φ).functor ⋙
119+
CostructuredArrow.proj (L ⋙ E.functor) (E.functor.obj Y) ⋙ F) :=
120+
(inferInstance : HasPointwiseLeftKanExtensionAt L F Y)
121+
exact hasColimit_of_equivalence_comp (asEquivalence Φ)
122+
123+
lemma hasPointwiseLeftKanExtensionAt_iff_of_equivalence
124+
(E : D ≌ D') (eL : L ⋙ E.functor ≅ L') (Y : D) (Y' : D') (e : E.functor.obj Y ≅ Y') :
125+
HasPointwiseLeftKanExtensionAt L F Y ↔
126+
HasPointwiseLeftKanExtensionAt L' F Y' := by
127+
constructor
128+
· intro
129+
exact hasPointwiseLeftKanExtensionAt_of_equivalence L L' F E eL Y Y' e
130+
· intro
131+
exact hasPointwiseLeftKanExtensionAt_of_equivalence L' L F E.symm
132+
(isoWhiskerRight eL.symm _ ≪≫ Functor.associator _ _ _ ≪≫
133+
isoWhiskerLeft L E.unitIso.symm ≪≫ L.rightUnitor) Y' Y
134+
(E.inverse.mapIso e.symm ≪≫ E.unitIso.symm.app Y)
135+
136+
lemma hasPointwiseRightKanExtensionAt_of_equivalence
137+
(E : D ≌ D') (eL : L ⋙ E.functor ≅ L') (Y : D) (Y' : D') (e : E.functor.obj Y ≅ Y')
138+
[HasPointwiseRightKanExtensionAt L F Y] :
139+
HasPointwiseRightKanExtensionAt L' F Y' := by
140+
rw [← hasPointwiseRightKanExtensionAt_iff_of_natIso F eL,
141+
hasPointwiseRightKanExtensionAt_iff_of_iso _ F e.symm]
142+
let Φ := StructuredArrow.post Y L E.functor
143+
have : HasLimit ((asEquivalence Φ).functor ⋙
144+
StructuredArrow.proj (E.functor.obj Y) (L ⋙ E.functor) ⋙ F) :=
145+
(inferInstance : HasPointwiseRightKanExtensionAt L F Y)
146+
exact hasLimit_of_equivalence_comp (asEquivalence Φ)
147+
148+
lemma hasPointwiseRightKanExtensionAt_iff_of_equivalence
149+
(E : D ≌ D') (eL : L ⋙ E.functor ≅ L') (Y : D) (Y' : D') (e : E.functor.obj Y ≅ Y') :
150+
HasPointwiseRightKanExtensionAt L F Y ↔
151+
HasPointwiseRightKanExtensionAt L' F Y' := by
152+
constructor
153+
· intro
154+
exact hasPointwiseRightKanExtensionAt_of_equivalence L L' F E eL Y Y' e
155+
· intro
156+
exact hasPointwiseRightKanExtensionAt_of_equivalence L' L F E.symm
157+
(isoWhiskerRight eL.symm _ ≪≫ Functor.associator _ _ _ ≪≫
158+
isoWhiskerLeft L E.unitIso.symm ≪≫ L.rightUnitor) Y' Y
159+
(E.inverse.mapIso e.symm ≪≫ E.unitIso.symm.app Y)
160+
58161
namespace LeftExtension
59162

60163
variable {F L}
@@ -98,6 +201,27 @@ lemma IsPointwiseLeftKanExtensionAt.isIso_hom_app
98201
IsIso (E.hom.app X) := by
99202
simpa using h.isIso_ι_app_of_isTerminal _ CostructuredArrow.mkIdTerminal
100203

204+
/-- The condition of being a pointwise left Kan extension at an object `Y` is
205+
unchanged by replacing `Y` by an isomorphic object `Y'`. -/
206+
def isPointwiseLeftKanExtensionAtOfIso'
207+
{Y : D} (hY : E.IsPointwiseLeftKanExtensionAt Y) {Y' : D} (e : Y ≅ Y') :
208+
E.IsPointwiseLeftKanExtensionAt Y' :=
209+
IsColimit.ofIsoColimit (hY.whiskerEquivalence (CostructuredArrow.mapIso e.symm))
210+
(Cocones.ext (E.right.mapIso e))
211+
212+
/-- The condition of being a pointwise left Kan extension at an object `Y` is
213+
unchanged by replacing `Y` by an isomorphic object `Y'`. -/
214+
def isPointwiseLeftKanExtensionAtEquivOfIso' {Y Y' : D} (e : Y ≅ Y') :
215+
E.IsPointwiseLeftKanExtensionAt Y ≃ E.IsPointwiseLeftKanExtensionAt Y' where
216+
toFun h := E.isPointwiseLeftKanExtensionAtOfIso' h e
217+
invFun h := E.isPointwiseLeftKanExtensionAtOfIso' h e.symm
218+
left_inv h := by
219+
dsimp only [IsPointwiseLeftKanExtensionAt]
220+
apply Subsingleton.elim
221+
right_inv h := by
222+
dsimp only [IsPointwiseLeftKanExtensionAt]
223+
apply Subsingleton.elim
224+
101225
namespace IsPointwiseLeftKanExtensionAt
102226

103227
variable {E} {Y : D} (h : E.IsPointwiseLeftKanExtensionAt Y)
@@ -235,6 +359,27 @@ lemma IsPointwiseRightKanExtensionAt.isIso_hom_app
235359
IsIso (E.hom.app X) := by
236360
simpa using h.isIso_π_app_of_isInitial _ StructuredArrow.mkIdInitial
237361

362+
/-- The condition of being a pointwise right Kan extension at an object `Y` is
363+
unchanged by replacing `Y` by an isomorphic object `Y'`. -/
364+
def isPointwiseRightKanExtensionAtOfIso'
365+
{Y : D} (hY : E.IsPointwiseRightKanExtensionAt Y) {Y' : D} (e : Y ≅ Y') :
366+
E.IsPointwiseRightKanExtensionAt Y' :=
367+
IsLimit.ofIsoLimit (hY.whiskerEquivalence (StructuredArrow.mapIso e.symm))
368+
(Cones.ext (E.left.mapIso e))
369+
370+
/-- The condition of being a pointwise right Kan extension at an object `Y` is
371+
unchanged by replacing `Y` by an isomorphic object `Y'`. -/
372+
def isPointwiseRightKanExtensionAtEquivOfIso' {Y Y' : D} (e : Y ≅ Y') :
373+
E.IsPointwiseRightKanExtensionAt Y ≃ E.IsPointwiseRightKanExtensionAt Y' where
374+
toFun h := E.isPointwiseRightKanExtensionAtOfIso' h e
375+
invFun h := E.isPointwiseRightKanExtensionAtOfIso' h e.symm
376+
left_inv h := by
377+
dsimp only [IsPointwiseRightKanExtensionAt]
378+
apply Subsingleton.elim
379+
right_inv h := by
380+
dsimp only [IsPointwiseRightKanExtensionAt]
381+
apply Subsingleton.elim
382+
238383
namespace IsPointwiseRightKanExtensionAt
239384

240385
variable {E} {Y : D} (h : E.IsPointwiseRightKanExtensionAt Y)

Mathlib/CategoryTheory/Limits/HasLimits.lean

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -433,18 +433,23 @@ theorem limit.pre_post {D : Type u'} [Category.{v'} D] (E : K ⥤ J) (F : J ⥤
433433

434434
open CategoryTheory.Equivalence
435435

436-
instance hasLimitEquivalenceComp (e : K ≌ J) [HasLimit F] : HasLimit (e.functor ⋙ F) :=
436+
instance hasLimit_equivalence_comp (e : K ≌ J) [HasLimit F] : HasLimit (e.functor ⋙ F) :=
437437
HasLimit.mk
438438
{ cone := Cone.whisker e.functor (limit.cone F)
439439
isLimit := IsLimit.whiskerEquivalence (limit.isLimit F) e }
440440

441441
-- not entirely sure why this is needed
442442
/-- If a `E ⋙ F` has a limit, and `E` is an equivalence, we can construct a limit of `F`.
443443
-/
444-
theorem hasLimitOfEquivalenceComp (e : K ≌ J) [HasLimit (e.functor ⋙ F)] : HasLimit F := by
445-
haveI : HasLimit (e.inverse ⋙ e.functor ⋙ F) := Limits.hasLimitEquivalenceComp e.symm
444+
theorem hasLimit_of_equivalence_comp (e : K ≌ J) [HasLimit (e.functor ⋙ F)] : HasLimit F := by
445+
haveI : HasLimit (e.inverse ⋙ e.functor ⋙ F) := Limits.hasLimit_equivalence_comp e.symm
446446
apply hasLimit_of_iso (e.invFunIdAssoc F)
447447

448+
@[deprecated (since := "2025-03-02")] alias hasLimitEquivalenceComp :=
449+
hasLimit_equivalence_comp
450+
@[deprecated (since := "2025-03-02")] alias hasLimitOfEquivalenceComp :=
451+
hasLimit_of_equivalence_comp
452+
448453
-- `hasLimitCompEquivalence` and `hasLimitOfCompEquivalence`
449454
-- are proved in `CategoryTheory/Adjunction/Limits.lean`.
450455
section LimFunctor
@@ -560,7 +565,7 @@ theorem hasLimitsOfShape_of_equivalence {J' : Type u₂} [Category.{v₂} J'] (e
560565
[HasLimitsOfShape J C] : HasLimitsOfShape J' C := by
561566
constructor
562567
intro F
563-
apply hasLimitOfEquivalenceComp e
568+
apply hasLimit_of_equivalence_comp e
564569

565570
variable (C)
566571

Mathlib/CategoryTheory/Limits/Opposites.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ variable [HasCoproduct Z]
558558
instance : HasLimit (Discrete.functor Z).op := hasLimit_op_of_hasColimit (Discrete.functor Z)
559559

560560
instance : HasLimit ((Discrete.opposite α).inverse ⋙ (Discrete.functor Z).op) :=
561-
hasLimitEquivalenceComp (Discrete.opposite α).symm
561+
hasLimit_equivalence_comp (Discrete.opposite α).symm
562562

563563
instance : HasProduct (op <| Z ·) := hasLimit_of_iso
564564
((Discrete.natIsoFunctor ≪≫ Discrete.natIso (fun _ ↦ by rfl)) :

Mathlib/CategoryTheory/Limits/Shapes/Products.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ lemma hasCoproduct_of_equiv_of_iso (f : α → C) (g : β → C)
102102
lemma hasProduct_of_equiv_of_iso (f : α → C) (g : β → C)
103103
[HasProduct f] (e : β ≃ α) (iso : ∀ j, g j ≅ f (e j)) : HasProduct g := by
104104
have : HasLimit ((Discrete.equivalence e).functor ⋙ Discrete.functor f) :=
105-
hasLimitEquivalenceComp _
105+
hasLimit_equivalence_comp _
106106
have α : Discrete.functor g ≅ (Discrete.equivalence e).functor ⋙ Discrete.functor f :=
107107
Discrete.natIso (fun ⟨j⟩ => iso j)
108108
exact hasLimit_of_iso α.symm

0 commit comments

Comments
 (0)