l3lab/ntp-mathlib huggingface dataset:
/-- (Implementation). The equivalence of homsets which helps construct the left adjoint to
`colimitAdj.restrictedYoneda`.
It is shown in `restrictYonedaHomEquivNatural` that this is a natural bijection.
-/
def restrictYonedaHomEquiv (P : Cᵒᵖ ⥤ Type u₁) (E : ℰ)
    {c : Cocone ((CategoryOfElements.π P).leftOp ⋙ A)} (t : IsColimit c) :
    (c.pt ⟶ E) ≃ (P ⟶ (restrictedYoneda A).obj E) :=
  ((uliftTrivial _).symm ≪≫ t.homIso' E).toEquiv.trans
    { toFun := fun k =>
        { app := fun c p => k.1 (Opposite.op ⟨_, p⟩)
          naturality := fun c c' f =>
            funext fun p =>
              (k.2
                  (Quiver.Hom.op ⟨f, rfl⟩ :
                    (Opposite.op ⟨c', P.map f p⟩ : P.Elementsᵒᵖ) ⟶ Opposite.op ⟨c, p⟩)).symm }
      invFun := fun τ =>
        { val := fun p => τ.app p.unop.1 p.unop.2
          property := @fun p p' f => by
            simp_rw [← f.unop.2]
            apply (congr_fun (τ.naturality f.unop.1) p'.unop.2).symm }
      left_inv := by
        rintro ⟨k₁, k₂⟩
        ext
        dsimp
        congr 1
      right_inv := by
        

Proof state:
C : Type u₁
inst✝¹ : SmallCategory C
ℰ : Type u₂
inst✝ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
P : Cᵒᵖ ⥤ Type u₁
E : ℰ
c : Cocone ((CategoryOfElements.π P).leftOp ⋙ A)
t : IsColimit c
⊢ Function.RightInverse
    (fun τ =>
      { val := fun p => τ.app p.unop.fst p.unop.snd,
        property :=
          (_ :
            ∀ (p p' : (Functor.Elements P)ᵒᵖ) (f : p ⟶ p'),
              ((CategoryOfElements.π P).leftOp ⋙ A).map f ≫ (fun p => τ.app p.unop.fst p.unop.snd) p' =
                (fun p => τ.app p.unop.fst p.unop.snd) p) })
    fun k => NatTrans.mk fun c p => ↑k (Opposite.op { fst := c, snd := p })

Next tactic:
rintro ⟨_, _⟩
/-- (Implementation). The equivalence of homsets which helps construct the left adjoint to
`colimitAdj.restrictedYoneda`.
It is shown in `restrictYonedaHomEquivNatural` that this is a natural bijection.
-/
def restrictYonedaHomEquiv (P : Cᵒᵖ ⥤ Type u₁) (E : ℰ)
    {c : Cocone ((CategoryOfElements.π P).leftOp ⋙ A)} (t : IsColimit c) :
    (c.pt ⟶ E) ≃ (P ⟶ (restrictedYoneda A).obj E) :=
  ((uliftTrivial _).symm ≪≫ t.homIso' E).toEquiv.trans
    { toFun := fun k =>
        { app := fun c p => k.1 (Opposite.op ⟨_, p⟩)
          naturality := fun c c' f =>
            funext fun p =>
              (k.2
                  (Quiver.Hom.op ⟨f, rfl⟩ :
                    (Opposite.op ⟨c', P.map f p⟩ : P.Elementsᵒᵖ) ⟶ Opposite.op ⟨c, p⟩)).symm }
      invFun := fun τ =>
        { val := fun p => τ.app p.unop.1 p.unop.2
          property := @fun p p' f => by
            simp_rw [← f.unop.2]
            apply (congr_fun (τ.naturality f.unop.1) p'.unop.2).symm }
      left_inv := by
        rintro ⟨k₁, k₂⟩
        ext
        dsimp
        congr 1
      right_inv := by
        rintro ⟨_, _⟩
        

Proof state:
case mk
C : Type u₁
inst✝¹ : SmallCategory C
ℰ : Type u₂
inst✝ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
P : Cᵒᵖ ⥤ Type u₁
E : ℰ
c : Cocone ((CategoryOfElements.π P).leftOp ⋙ A)
t : IsColimit c
app✝ : (X : Cᵒᵖ) → P.obj X ⟶ ((restrictedYoneda A).obj E).obj X
naturality✝ : ∀ ⦃X Y : Cᵒᵖ⦄ (f : X ⟶ Y), P.map f ≫ app✝ Y = app✝ X ≫ ((restrictedYoneda A).obj E).map f
⊢ (fun k => NatTrans.mk fun c p => ↑k (Opposite.op { fst := c, snd := p }))
      ((fun τ =>
          { val := fun p => τ.app p.unop.fst p.unop.snd,
            property :=
              (_ :
                ∀ (p p' : (Functor.Elements P)ᵒᵖ) (f : p ⟶ p'),
                  ((CategoryOfElements.π P).leftOp ⋙ A).map f ≫ (fun p => τ.app p.unop.fst p.unop.snd) p' =
                    (fun p => τ.app p.unop.fst p.unop.snd) p) })
        (NatTrans.mk app✝)) =
    NatTrans.mk app✝

Next tactic:
rfl
/--
(Implementation). Show that the bijection in `restrictYonedaHomEquiv` is natural (on the right).
-/
theorem restrictYonedaHomEquiv_natural (P : Cᵒᵖ ⥤ Type u₁) (E₁ E₂ : ℰ) (g : E₁ ⟶ E₂) {c : Cocone _}
    (t : IsColimit c) (k : c.pt ⟶ E₁) :
    restrictYonedaHomEquiv A P E₂ t (k ≫ g) =
      restrictYonedaHomEquiv A P E₁ t k ≫ (restrictedYoneda A).map g := by
  

Proof state:
C : Type u₁
inst✝¹ : SmallCategory C
ℰ : Type u₂
inst✝ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
P : Cᵒᵖ ⥤ Type u₁
E₁ E₂ : ℰ
g : E₁ ⟶ E₂
c : Cocone ((CategoryOfElements.π P).leftOp ⋙ A)
t : IsColimit c
k : c.pt ⟶ E₁
⊢ (restrictYonedaHomEquiv A P E₂ t) (k ≫ g) = (restrictYonedaHomEquiv A P E₁ t) k ≫ (restrictedYoneda A).map g

Next tactic:
ext x X
/--
(Implementation). Show that the bijection in `restrictYonedaHomEquiv` is natural (on the right).
-/
theorem restrictYonedaHomEquiv_natural (P : Cᵒᵖ ⥤ Type u₁) (E₁ E₂ : ℰ) (g : E₁ ⟶ E₂) {c : Cocone _}
    (t : IsColimit c) (k : c.pt ⟶ E₁) :
    restrictYonedaHomEquiv A P E₂ t (k ≫ g) =
      restrictYonedaHomEquiv A P E₁ t k ≫ (restrictedYoneda A).map g := by
  ext x X
  

Proof state:
case w.h.h
C : Type u₁
inst✝¹ : SmallCategory C
ℰ : Type u₂
inst✝ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
P : Cᵒᵖ ⥤ Type u₁
E₁ E₂ : ℰ
g : E₁ ⟶ E₂
c : Cocone ((CategoryOfElements.π P).leftOp ⋙ A)
t : IsColimit c
k : c.pt ⟶ E₁
x : Cᵒᵖ
X : P.obj x
⊢ ((restrictYonedaHomEquiv A P E₂ t) (k ≫ g)).app x X =
    ((restrictYonedaHomEquiv A P E₁ t) k ≫ (restrictedYoneda A).map g).app x X

Next tactic:
apply (assoc _ _ _).symm
theorem extendAlongYoneda_map {X Y : Cᵒᵖ ⥤ Type u₁} (f : X ⟶ Y) :
    (extendAlongYoneda A).map f =
      colimit.pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op := by
  

Proof state:
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : Cᵒᵖ ⥤ Type u₁
f : X ⟶ Y
⊢ (extendAlongYoneda A).map f = colimit.pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op

Next tactic:
ext J
theorem extendAlongYoneda_map {X Y : Cᵒᵖ ⥤ Type u₁} (f : X ⟶ Y) :
    (extendAlongYoneda A).map f =
      colimit.pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op := by
  ext J
  

Proof state:
case w
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : Cᵒᵖ ⥤ Type u₁
f : X ⟶ Y
J : (Functor.Elements X)ᵒᵖ
⊢ colimit.ι ((CategoryOfElements.π X).leftOp ⋙ A) J ≫ (extendAlongYoneda A).map f =
    colimit.ι ((CategoryOfElements.π X).leftOp ⋙ A) J ≫
      colimit.pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op

Next tactic:
erw [colimit.ι_pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op]
theorem extendAlongYoneda_map {X Y : Cᵒᵖ ⥤ Type u₁} (f : X ⟶ Y) :
    (extendAlongYoneda A).map f =
      colimit.pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op := by
  ext J
  erw [colimit.ι_pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op]
  

Proof state:
case w
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : Cᵒᵖ ⥤ Type u₁
f : X ⟶ Y
J : (Functor.Elements X)ᵒᵖ
⊢ colimit.ι ((CategoryOfElements.π X).leftOp ⋙ A) J ≫ (extendAlongYoneda A).map f =
    colimit.ι ((CategoryOfElements.π Y).leftOp ⋙ A) ((CategoryOfElements.map f).op.obj J)

Next tactic:
dsimp only [extendAlongYoneda, restrictYonedaHomEquiv, IsColimit.homIso', IsColimit.homIso,
    uliftTrivial]
theorem extendAlongYoneda_map {X Y : Cᵒᵖ ⥤ Type u₁} (f : X ⟶ Y) :
    (extendAlongYoneda A).map f =
      colimit.pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op := by
  ext J
  erw [colimit.ι_pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op]
  dsimp only [extendAlongYoneda, restrictYonedaHomEquiv, IsColimit.homIso', IsColimit.homIso,
    uliftTrivial]
  -- porting note: in mathlib3 the rest of the proof was `simp, refl`; this is squeezed
  -- and appropriately reordered, presumably because of a non-confluence issue.
  simp only [Adjunction.leftAdjointOfEquiv_map, Iso.symm_mk, Iso.toEquiv_comp, Equiv.coe_trans,
    Equiv.coe_fn_mk, Iso.toEquiv_fun, Equiv.symm_trans_apply, Equiv.coe_fn_symm_mk,
    Iso.toEquiv_symm_fun, id.def, colimit.isColimit_desc, colimit.ι_desc, FunctorToTypes.comp,
    Cocone.extend_ι, Cocone.extensions_app, Functor.map_id, Category.comp_id, colimit.cocone_ι]
  

Proof state:
case w
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : Cᵒᵖ ⥤ Type u₁
f : X ⟶ Y
J : (Functor.Elements X)ᵒᵖ
⊢ (((fun k => NatTrans.mk fun c p => ↑k (Opposite.op { fst := c, snd := p })) ∘
            ((fun ι =>
                  { val := fun j => ι.app j,
                    property :=
                      (_ :
                        ∀ {j j' : (Functor.Elements Y)ᵒᵖ} (f : j ⟶ j'),
                          ((CategoryOfElements.π Y).leftOp ⋙ A).map f ≫ (fun j => ι.app j) j' =
                            (fun j => ι.app j) j) }) ∘
                fun f =>
                (colimit.cocone ((CategoryOfElements.π Y).leftOp ⋙ A)).ι ≫
                  (Functor.const (Functor.Elements Y)ᵒᵖ).map f.down) ∘
              fun a => { down := a })
          (𝟙 (colimit.cocone ((CategoryOfElements.π Y).leftOp ⋙ A)).pt)).app
      J.unop.fst (f.app J.unop.fst J.unop.snd) =
    colimit.ι ((CategoryOfElements.π Y).leftOp ⋙ A) ((CategoryOfElements.map f).op.obj J)

Next tactic:
simp only [Functor.comp_obj, Functor.leftOp_obj, CategoryOfElements.π_obj, colimit.cocone_x,
    Functor.comp_map, Functor.leftOp_map, CategoryOfElements.π_map, Opposite.unop_op,
    Adjunction.leftAdjointOfEquiv_obj, Function.comp_apply, Functor.map_id, comp_id,
    colimit.cocone_ι, Functor.op_obj]
theorem extendAlongYoneda_map {X Y : Cᵒᵖ ⥤ Type u₁} (f : X ⟶ Y) :
    (extendAlongYoneda A).map f =
      colimit.pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op := by
  ext J
  erw [colimit.ι_pre ((CategoryOfElements.π Y).leftOp ⋙ A) (CategoryOfElements.map f).op]
  dsimp only [extendAlongYoneda, restrictYonedaHomEquiv, IsColimit.homIso', IsColimit.homIso,
    uliftTrivial]
  -- porting note: in mathlib3 the rest of the proof was `simp, refl`; this is squeezed
  -- and appropriately reordered, presumably because of a non-confluence issue.
  simp only [Adjunction.leftAdjointOfEquiv_map, Iso.symm_mk, Iso.toEquiv_comp, Equiv.coe_trans,
    Equiv.coe_fn_mk, Iso.toEquiv_fun, Equiv.symm_trans_apply, Equiv.coe_fn_symm_mk,
    Iso.toEquiv_symm_fun, id.def, colimit.isColimit_desc, colimit.ι_desc, FunctorToTypes.comp,
    Cocone.extend_ι, Cocone.extensions_app, Functor.map_id, Category.comp_id, colimit.cocone_ι]
  simp only [Functor.comp_obj, Functor.leftOp_obj, CategoryOfElements.π_obj, colimit.cocone_x,
    Functor.comp_map, Functor.leftOp_map, CategoryOfElements.π_map, Opposite.unop_op,
    Adjunction.leftAdjointOfEquiv_obj, Function.comp_apply, Functor.map_id, comp_id,
    colimit.cocone_ι, Functor.op_obj]
  

Proof state:
case w
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : Cᵒᵖ ⥤ Type u₁
f : X ⟶ Y
J : (Functor.Elements X)ᵒᵖ
⊢ colimit.ι ((CategoryOfElements.π Y).leftOp ⋙ A)
      (Opposite.op { fst := J.unop.fst, snd := f.app J.unop.fst J.unop.snd }) =
    colimit.ι ((CategoryOfElements.π Y).leftOp ⋙ A) (Opposite.op ((CategoryOfElements.map f).obj J.unop))

Next tactic:
rfl
/-- Show that `Elements.initial A` is initial in the category of elements for the `yoneda` functor.
-/
def isInitial (A : C) : IsInitial (Elements.initial A) where
  desc s := ⟨s.pt.2.op, comp_id _⟩
  uniq s m _ := by
    simp_rw [← m.2]
    dsimp [Elements.initial]
    simp
  fac := by 

Proof state:
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A✝ : C ⥤ ℰ
inst✝ : HasColimits ℰ
A : C
⊢ ∀ (s : Cocone (Functor.empty (Functor.Elements (yoneda.obj A)))) (j : Discrete PEmpty.{1}),
    (asEmptyCocone (Elements.initial A)).ι.app j ≫
        (fun s =>
            { val := s.pt.snd.op,
              property :=
                (_ : s.pt.snd.op.unop ≫ 𝟙 (asEmptyCocone (Elements.initial A)).pt.fst.unop = s.pt.snd.op.unop) })
          s =
      s.ι.app j

Next tactic:
rintro s ⟨⟨⟩⟩
/-- Show that `Elements.initial A` is initial in the category of elements for the `yoneda` functor.
-/
def isInitial (A : C) : IsInitial (Elements.initial A) where
  desc s := ⟨s.pt.2.op, comp_id _⟩
  uniq s m _ := by
    

Proof state:
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A✝ : C ⥤ ℰ
inst✝ : HasColimits ℰ
A : C
s : Cocone (Functor.empty (Functor.Elements (yoneda.obj A)))
m : (asEmptyCocone (Elements.initial A)).pt ⟶ s.pt
x✝ : ∀ (j : Discrete PEmpty.{1}), (asEmptyCocone (Elements.initial A)).ι.app j ≫ m = s.ι.app j
⊢ m =
    (fun s =>
        { val := s.pt.snd.op,
          property := (_ : s.pt.snd.op.unop ≫ 𝟙 (asEmptyCocone (Elements.initial A)).pt.fst.unop = s.pt.snd.op.unop) })
      s

Next tactic:
simp_rw [← m.2]
/-- Show that `Elements.initial A` is initial in the category of elements for the `yoneda` functor.
-/
def isInitial (A : C) : IsInitial (Elements.initial A) where
  desc s := ⟨s.pt.2.op, comp_id _⟩
  uniq s m _ := by
    simp_rw [← m.2]
    

Proof state:
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A✝ : C ⥤ ℰ
inst✝ : HasColimits ℰ
A : C
s : Cocone (Functor.empty (Functor.Elements (yoneda.obj A)))
m : (asEmptyCocone (Elements.initial A)).pt ⟶ s.pt
x✝ : ∀ (j : Discrete PEmpty.{1}), (asEmptyCocone (Elements.initial A)).ι.app j ≫ m = s.ι.app j
⊢ m =
    { val := ((yoneda.obj A).map (↑m) (asEmptyCocone (Elements.initial A)).pt.snd).op,
      property :=
        (_ :
          (fun f => (yoneda.obj A).map f (asEmptyCocone (Elements.initial A)).pt.snd = s.pt.snd)
            ((yoneda.obj A).map (↑m) (asEmptyCocone (Elements.initial A)).pt.snd).op) }

Next tactic:
dsimp [Elements.initial]
/-- Show that `Elements.initial A` is initial in the category of elements for the `yoneda` functor.
-/
def isInitial (A : C) : IsInitial (Elements.initial A) where
  desc s := ⟨s.pt.2.op, comp_id _⟩
  uniq s m _ := by
    simp_rw [← m.2]
    dsimp [Elements.initial]
    

Proof state:
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A✝ : C ⥤ ℰ
inst✝ : HasColimits ℰ
A : C
s : Cocone (Functor.empty (Functor.Elements (yoneda.obj A)))
m : (asEmptyCocone (Elements.initial A)).pt ⟶ s.pt
x✝ : ∀ (j : Discrete PEmpty.{1}), (asEmptyCocone (Elements.initial A)).ι.app j ≫ m = s.ι.app j
⊢ m = { val := 𝟙 (Opposite.op A) ≫ ↑m, property := (_ : (𝟙 (Opposite.op A) ≫ ↑m).unop ≫ 𝟙 A = s.pt.snd) }

Next tactic:
simp
/--
`extendAlongYoneda A` is an extension of `A` to the presheaf category along the yoneda embedding.
`uniqueExtensionAlongYoneda` shows it is unique among functors preserving colimits with this
property (up to isomorphism).

The first part of [MM92], Chapter I, Section 5, Corollary 4.
See Property 1 of <https://ncatlab.org/nlab/show/Yoneda+extension#properties>.
-/
noncomputable def isExtensionAlongYoneda :
    (yoneda : C ⥤ Cᵒᵖ ⥤ Type u₁) ⋙ extendAlongYoneda A ≅ A :=
  NatIso.ofComponents
    (fun X =>
      (colimit.isColimit _).coconePointUniqueUpToIso
        (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial _)) _))
    (by
      

Proof state:
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
⊢ ∀ {X Y : C} (f : X ⟶ Y),
    (yoneda ⋙ extendAlongYoneda A).map f ≫
        ((fun X =>
              IsColimit.coconePointUniqueUpToIso (colimit.isColimit ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A))
                (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial X))
                  ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A)))
            Y).hom =
      ((fun X =>
              IsColimit.coconePointUniqueUpToIso (colimit.isColimit ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A))
                (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial X))
                  ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A)))
            X).hom ≫
        A.map f

Next tactic:
intro X Y f
/--
`extendAlongYoneda A` is an extension of `A` to the presheaf category along the yoneda embedding.
`uniqueExtensionAlongYoneda` shows it is unique among functors preserving colimits with this
property (up to isomorphism).

The first part of [MM92], Chapter I, Section 5, Corollary 4.
See Property 1 of <https://ncatlab.org/nlab/show/Yoneda+extension#properties>.
-/
noncomputable def isExtensionAlongYoneda :
    (yoneda : C ⥤ Cᵒᵖ ⥤ Type u₁) ⋙ extendAlongYoneda A ≅ A :=
  NatIso.ofComponents
    (fun X =>
      (colimit.isColimit _).coconePointUniqueUpToIso
        (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial _)) _))
    (by
      intro X Y f
      -- porting note: this is slightly different to the `change` in mathlib3 which
      -- didn't work
      

Proof state:
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : C
f : X ⟶ Y
⊢ (yoneda ⋙ extendAlongYoneda A).map f ≫
      ((fun X =>
            IsColimit.coconePointUniqueUpToIso (colimit.isColimit ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A))
              (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial X))
                ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A)))
          Y).hom =
    ((fun X =>
            IsColimit.coconePointUniqueUpToIso (colimit.isColimit ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A))
              (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial X))
                ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A)))
          X).hom ≫
      A.map f

Next tactic:
change (colimit.desc _ _ ≫ _) = colimit.desc _ _ ≫ _
/--
`extendAlongYoneda A` is an extension of `A` to the presheaf category along the yoneda embedding.
`uniqueExtensionAlongYoneda` shows it is unique among functors preserving colimits with this
property (up to isomorphism).

The first part of [MM92], Chapter I, Section 5, Corollary 4.
See Property 1 of <https://ncatlab.org/nlab/show/Yoneda+extension#properties>.
-/
noncomputable def isExtensionAlongYoneda :
    (yoneda : C ⥤ Cᵒᵖ ⥤ Type u₁) ⋙ extendAlongYoneda A ≅ A :=
  NatIso.ofComponents
    (fun X =>
      (colimit.isColimit _).coconePointUniqueUpToIso
        (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial _)) _))
    (by
      intro X Y f
      -- porting note: this is slightly different to the `change` in mathlib3 which
      -- didn't work
      change (colimit.desc _ _ ≫ _) = colimit.desc _ _ ≫ _
      ext
      rw [colimit.ι_desc_assoc, colimit.ι_desc_assoc]
      change (colimit.ι _ _ ≫ 𝟙 _) ≫ colimit.desc _ _ = _
      

Proof state:
case w
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : C
f : X ⟶ Y
j✝ : (Functor.Elements (yoneda.obj X))ᵒᵖ
⊢ (colimit.ι (Opposite.op ((CategoryOfElements.π (yoneda.obj Y)).leftOp ⋙ A)).unop
          (Opposite.op { fst := j✝.unop.fst, snd := (yoneda.map f).app j✝.unop.fst j✝.unop.snd }) ≫
        𝟙 (colimit (Opposite.op ((CategoryOfElements.π (yoneda.obj Y)).leftOp ⋙ A)).unop)) ≫
      colimit.desc (Opposite.op ((CategoryOfElements.π (yoneda.obj Y)).leftOp ⋙ A)).unop
        (coconeOfDiagramTerminal (terminalOpOfInitial (isInitial Y))
          ((CategoryOfElements.π (yoneda.obj Y)).leftOp ⋙ A)) =
    (coconeOfDiagramTerminal (terminalOpOfInitial (isInitial X))
              ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A)).ι.app
        j✝ ≫
      A.map f

Next tactic:
rw [comp_id, colimit.ι_desc]
/--
`extendAlongYoneda A` is an extension of `A` to the presheaf category along the yoneda embedding.
`uniqueExtensionAlongYoneda` shows it is unique among functors preserving colimits with this
property (up to isomorphism).

The first part of [MM92], Chapter I, Section 5, Corollary 4.
See Property 1 of <https://ncatlab.org/nlab/show/Yoneda+extension#properties>.
-/
noncomputable def isExtensionAlongYoneda :
    (yoneda : C ⥤ Cᵒᵖ ⥤ Type u₁) ⋙ extendAlongYoneda A ≅ A :=
  NatIso.ofComponents
    (fun X =>
      (colimit.isColimit _).coconePointUniqueUpToIso
        (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial _)) _))
    (by
      intro X Y f
      -- porting note: this is slightly different to the `change` in mathlib3 which
      -- didn't work
      change (colimit.desc _ _ ≫ _) = colimit.desc _ _ ≫ _
      ext
      rw [colimit.ι_desc_assoc, colimit.ι_desc_assoc]
      change (colimit.ι _ _ ≫ 𝟙 _) ≫ colimit.desc _ _ = _
      rw [comp_id, colimit.ι_desc]
      

Proof state:
case w
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : C
f : X ⟶ Y
j✝ : (Functor.Elements (yoneda.obj X))ᵒᵖ
⊢ (coconeOfDiagramTerminal (terminalOpOfInitial (isInitial Y)) ((CategoryOfElements.π (yoneda.obj Y)).leftOp ⋙ A)).ι.app
      (Opposite.op { fst := j✝.unop.fst, snd := (yoneda.map f).app j✝.unop.fst j✝.unop.snd }) =
    (coconeOfDiagramTerminal (terminalOpOfInitial (isInitial X))
              ((CategoryOfElements.π (yoneda.obj X)).leftOp ⋙ A)).ι.app
        j✝ ≫
      A.map f

Next tactic:
dsimp
/--
`extendAlongYoneda A` is an extension of `A` to the presheaf category along the yoneda embedding.
`uniqueExtensionAlongYoneda` shows it is unique among functors preserving colimits with this
property (up to isomorphism).

The first part of [MM92], Chapter I, Section 5, Corollary 4.
See Property 1 of <https://ncatlab.org/nlab/show/Yoneda+extension#properties>.
-/
noncomputable def isExtensionAlongYoneda :
    (yoneda : C ⥤ Cᵒᵖ ⥤ Type u₁) ⋙ extendAlongYoneda A ≅ A :=
  NatIso.ofComponents
    (fun X =>
      (colimit.isColimit _).coconePointUniqueUpToIso
        (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial _)) _))
    (by
      intro X Y f
      -- porting note: this is slightly different to the `change` in mathlib3 which
      -- didn't work
      change (colimit.desc _ _ ≫ _) = colimit.desc _ _ ≫ _
      ext
      rw [colimit.ι_desc_assoc, colimit.ι_desc_assoc]
      change (colimit.ι _ _ ≫ 𝟙 _) ≫ colimit.desc _ _ = _
      rw [comp_id, colimit.ι_desc]
      dsimp
      

Proof state:
case w
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : C
f : X ⟶ Y
j✝ : (Functor.Elements (yoneda.obj X))ᵒᵖ
⊢ A.map
      (↑(IsTerminal.from (terminalOpOfInitial (isInitial Y))
              (Opposite.op { fst := j✝.unop.fst, snd := j✝.unop.snd ≫ f })).unop).unop =
    A.map (↑(IsTerminal.from (terminalOpOfInitial (isInitial X)) j✝).unop).unop ≫ A.map f

Next tactic:
rw [← A.map_comp]
/--
`extendAlongYoneda A` is an extension of `A` to the presheaf category along the yoneda embedding.
`uniqueExtensionAlongYoneda` shows it is unique among functors preserving colimits with this
property (up to isomorphism).

The first part of [MM92], Chapter I, Section 5, Corollary 4.
See Property 1 of <https://ncatlab.org/nlab/show/Yoneda+extension#properties>.
-/
noncomputable def isExtensionAlongYoneda :
    (yoneda : C ⥤ Cᵒᵖ ⥤ Type u₁) ⋙ extendAlongYoneda A ≅ A :=
  NatIso.ofComponents
    (fun X =>
      (colimit.isColimit _).coconePointUniqueUpToIso
        (colimitOfDiagramTerminal (terminalOpOfInitial (isInitial _)) _))
    (by
      intro X Y f
      -- porting note: this is slightly different to the `change` in mathlib3 which
      -- didn't work
      change (colimit.desc _ _ ≫ _) = colimit.desc _ _ ≫ _
      ext
      rw [colimit.ι_desc_assoc, colimit.ι_desc_assoc]
      change (colimit.ι _ _ ≫ 𝟙 _) ≫ colimit.desc _ _ = _
      rw [comp_id, colimit.ι_desc]
      dsimp
      rw [← A.map_comp]
      

Proof state:
case w
C : Type u₁
inst✝² : SmallCategory C
ℰ : Type u₂
inst✝¹ : Category.{u₁, u₂} ℰ
A : C ⥤ ℰ
inst✝ : HasColimits ℰ
X Y : C
f : X ⟶ Y
j✝ : (Functor.Elements (yoneda.obj X))ᵒᵖ
⊢ A.map
      (↑(IsTerminal.from (terminalOpOfInitial (isInitial Y))
              (Opposite.op { fst := j✝.unop.fst, snd := j✝.unop.snd ≫ f })).unop).unop =
    A.map ((↑(IsTerminal.from (terminalOpOfInitial (isInitial X)) j✝).unop).unop ≫ f)

Next tactic:
congr 1