l3lab/ntp-mathlib huggingface dataset:
/-- If `F.cones` is represented by `X`, the cone corresponding to a morphism `f : Y ⟶ X` is
the limit cone extended by `f`. -/
theorem coneOfHom_fac {Y : C} (f : Y ⟶ X) : coneOfHom h f = (limitCone h).extend f := by
  dsimp [coneOfHom, limitCone, Cone.extend]
  congr with j
  have t := congrFun (h.hom.naturality f.op) ⟨𝟙 X⟩
  

Proof state:
case e_π.w.h
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t✝ : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
Y : C
f : Y ⟶ X
j : J
t :
  ((yoneda.obj X ⋙ uliftFunctor.{u₁, v₃}).map f.op ≫ h.hom.app (op Y)) { down := 𝟙 X } =
    (h.hom.app (op X) ≫ (Functor.cones F).map f.op) { down := 𝟙 X }
⊢ (h.hom.app (op Y) { down := f }).app j = ((const J).map f ≫ h.hom.app (op X) { down := 𝟙 X }).app j

Next tactic:
dsimp at t
/-- If `F.cones` is represented by `X`, the cone corresponding to a morphism `f : Y ⟶ X` is
the limit cone extended by `f`. -/
theorem coneOfHom_fac {Y : C} (f : Y ⟶ X) : coneOfHom h f = (limitCone h).extend f := by
  dsimp [coneOfHom, limitCone, Cone.extend]
  congr with j
  have t := congrFun (h.hom.naturality f.op) ⟨𝟙 X⟩
  dsimp at t
  

Proof state:
case e_π.w.h
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t✝ : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
Y : C
f : Y ⟶ X
j : J
t : h.hom.app (op Y) { down := f ≫ 𝟙 X } = (Functor.cones F).map f.op (h.hom.app (op X) { down := 𝟙 X })
⊢ (h.hom.app (op Y) { down := f }).app j = ((const J).map f ≫ h.hom.app (op X) { down := 𝟙 X }).app j

Next tactic:
simp only [comp_id] at t
/-- If `F.cones` is represented by `X`, the cone corresponding to a morphism `f : Y ⟶ X` is
the limit cone extended by `f`. -/
theorem coneOfHom_fac {Y : C} (f : Y ⟶ X) : coneOfHom h f = (limitCone h).extend f := by
  dsimp [coneOfHom, limitCone, Cone.extend]
  congr with j
  have t := congrFun (h.hom.naturality f.op) ⟨𝟙 X⟩
  dsimp at t
  simp only [comp_id] at t
  

Proof state:
case e_π.w.h
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t✝ : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
Y : C
f : Y ⟶ X
j : J
t : h.hom.app (op Y) { down := f } = (Functor.cones F).map f.op (h.hom.app (op X) { down := 𝟙 X })
⊢ (h.hom.app (op Y) { down := f }).app j = ((const J).map f ≫ h.hom.app (op X) { down := 𝟙 X }).app j

Next tactic:
rw [congrFun (congrArg NatTrans.app t) j]
/-- If `F.cones` is represented by `X`, the cone corresponding to a morphism `f : Y ⟶ X` is
the limit cone extended by `f`. -/
theorem coneOfHom_fac {Y : C} (f : Y ⟶ X) : coneOfHom h f = (limitCone h).extend f := by
  dsimp [coneOfHom, limitCone, Cone.extend]
  congr with j
  have t := congrFun (h.hom.naturality f.op) ⟨𝟙 X⟩
  dsimp at t
  simp only [comp_id] at t
  rw [congrFun (congrArg NatTrans.app t) j]
  

Proof state:
case e_π.w.h
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t✝ : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
Y : C
f : Y ⟶ X
j : J
t : h.hom.app (op Y) { down := f } = (Functor.cones F).map f.op (h.hom.app (op X) { down := 𝟙 X })
⊢ ((Functor.cones F).map f.op (h.hom.app (op X) { down := 𝟙 X })).app j =
    ((const J).map f ≫ h.hom.app (op X) { down := 𝟙 X }).app j

Next tactic:
rfl
/-- If `F.cones` is represented by `X`, any cone is the extension of the limit cone by the
corresponding morphism. -/
theorem cone_fac (s : Cone F) : (limitCone h).extend (homOfCone h s) = s := by
  

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
⊢ Cone.extend (limitCone h) (homOfCone h s) = s

Next tactic:
rw [← coneOfHom_homOfCone h s]
/-- If `F.cones` is represented by `X`, any cone is the extension of the limit cone by the
corresponding morphism. -/
theorem cone_fac (s : Cone F) : (limitCone h).extend (homOfCone h s) = s := by
  rw [← coneOfHom_homOfCone h s]
  

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
⊢ Cone.extend (limitCone h) (homOfCone h (coneOfHom h (homOfCone h s))) = coneOfHom h (homOfCone h s)

Next tactic:
conv_lhs => simp only [homOfCone_coneOfHom]
/-- If `F.cones` is represented by `X`, any cone is the extension of the limit cone by the
corresponding morphism. -/
theorem cone_fac (s : Cone F) : (limitCone h).extend (homOfCone h s) = s := by
  rw [← coneOfHom_homOfCone h s]
  conv_lhs => 

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
| Cone.extend (limitCone h) (homOfCone h (coneOfHom h (homOfCone h s)))

Next tactic:
simp only [homOfCone_coneOfHom]
/-- If `F.cones` is represented by `X`, any cone is the extension of the limit cone by the
corresponding morphism. -/
theorem cone_fac (s : Cone F) : (limitCone h).extend (homOfCone h s) = s := by
  rw [← coneOfHom_homOfCone h s]
  conv_lhs => simp only [homOfCone_coneOfHom]
  

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
⊢ Cone.extend (limitCone h) (homOfCone h s) = coneOfHom h (homOfCone h s)

Next tactic:
apply (coneOfHom_fac _ _).symm
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
j : J
⊢ (fun s => homOfCone h s) s ≫ (limitCone h).π.app j = s.π.app j

Next tactic:
have h := cone_fac h s
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h✝ : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
j : J
h : Cone.extend (limitCone h✝) (homOfCone h✝ s) = s
⊢ (fun s => homOfCone h✝ s) s ≫ (limitCone h✝).π.app j = s.π.app j

Next tactic:
cases s
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    

Proof state:
case mk
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h✝ : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
j : J
pt✝ : C
π✝ : (const J).obj pt✝ ⟶ F
h : Cone.extend (limitCone h✝) (homOfCone h✝ { pt := pt✝, π := π✝ }) = { pt := pt✝, π := π✝ }
⊢ (fun s => homOfCone h✝ s) { pt := pt✝, π := π✝ } ≫ (limitCone h✝).π.app j = { pt := pt✝, π := π✝ }.π.app j

Next tactic:
injection h with h₁ h₂
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    

Proof state:
case mk
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
j : J
pt✝ : C
π✝ : (const J).obj pt✝ ⟶ F
h₁ : { pt := pt✝, π := π✝ }.pt = pt✝
h₂ :
  (Cone.extensions (limitCone h)).app (op { pt := pt✝, π := π✝ }.pt) { down := homOfCone h { pt := pt✝, π := π✝ } } = π✝
⊢ (fun s => homOfCone h s) { pt := pt✝, π := π✝ } ≫ (limitCone h).π.app j = { pt := pt✝, π := π✝ }.π.app j

Next tactic:
simp only [heq_iff_eq] at h₂
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    

Proof state:
case mk
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
j : J
pt✝ : C
π✝ : (const J).obj pt✝ ⟶ F
h₁ : { pt := pt✝, π := π✝ }.pt = pt✝
h₂ : (Cone.extensions (limitCone h)).app (op pt✝) { down := homOfCone h { pt := pt✝, π := π✝ } } = π✝
⊢ (fun s => homOfCone h s) { pt := pt✝, π := π✝ } ≫ (limitCone h).π.app j = { pt := pt✝, π := π✝ }.π.app j

Next tactic:
conv_rhs => rw [← h₂]; rfl
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => 

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
j : J
pt✝ : C
π✝ : (const J).obj pt✝ ⟶ F
h₁ : { pt := pt✝, π := π✝ }.pt = pt✝
h₂ : (Cone.extensions (limitCone h)).app (op pt✝) { down := homOfCone h { pt := pt✝, π := π✝ } } = π✝
| { pt := pt✝, π := π✝ }.π.app j

Next tactic:
rw [← h₂]; rfl
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => 

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
j : J
pt✝ : C
π✝ : (const J).obj pt✝ ⟶ F
h₁ : { pt := pt✝, π := π✝ }.pt = pt✝
h₂ : (Cone.extensions (limitCone h)).app (op pt✝) { down := homOfCone h { pt := pt✝, π := π✝ } } = π✝
| { pt := pt✝, π := π✝ }.π.app j

Next tactic:
rw [← h₂]
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => rw [← h₂]; 

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
j : J
pt✝ : C
π✝ : (const J).obj pt✝ ⟶ F
h₁ : { pt := pt✝, π := π✝ }.pt = pt✝
h₂ : (Cone.extensions (limitCone h)).app (op pt✝) { down := homOfCone h { pt := pt✝, π := π✝ } } = π✝
| { pt := pt✝, π := (Cone.extensions (limitCone h)).app (op pt✝) { down := homOfCone h { pt := pt✝, π := π✝ } } }.π.app
    j

Next tactic:
rfl
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => rw [← h₂]; rfl
  uniq s m w := by
    

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
m : s.pt ⟶ (limitCone h).pt
w : ∀ (j : J), m ≫ (limitCone h).π.app j = s.π.app j
⊢ m = (fun s => homOfCone h s) s

Next tactic:
rw [← homOfCone_coneOfHom h m]
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => rw [← h₂]; rfl
  uniq s m w := by
    rw [← homOfCone_coneOfHom h m]
    

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
m : s.pt ⟶ (limitCone h).pt
w : ∀ (j : J), m ≫ (limitCone h).π.app j = s.π.app j
⊢ homOfCone h (coneOfHom h m) = (fun s => homOfCone h s) s

Next tactic:
congr
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => rw [← h₂]; rfl
  uniq s m w := by
    rw [← homOfCone_coneOfHom h m]
    congr
    

Proof state:
case h.e_8.h
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
m : s.pt ⟶ (limitCone h).pt
w : ∀ (j : J), m ≫ (limitCone h).π.app j = s.π.app j
⊢ coneOfHom h m = s

Next tactic:
rw [coneOfHom_fac]
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => rw [← h₂]; rfl
  uniq s m w := by
    rw [← homOfCone_coneOfHom h m]
    congr
    rw [coneOfHom_fac]
    

Proof state:
case h.e_8.h
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
m : s.pt ⟶ (limitCone h).pt
w : ∀ (j : J), m ≫ (limitCone h).π.app j = s.π.app j
⊢ Cone.extend (limitCone h) m = s

Next tactic:
dsimp [Cone.extend]
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => rw [← h₂]; rfl
  uniq s m w := by
    rw [← homOfCone_coneOfHom h m]
    congr
    rw [coneOfHom_fac]
    dsimp [Cone.extend]; 

Proof state:
case h.e_8.h
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
s : Cone F
m : s.pt ⟶ (limitCone h).pt
w : ∀ (j : J), m ≫ (limitCone h).π.app j = s.π.app j
⊢ { pt := s.pt, π := (const J).map m ≫ (limitCone h).π } = s

Next tactic:
cases s
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => rw [← h₂]; rfl
  uniq s m w := by
    rw [← homOfCone_coneOfHom h m]
    congr
    rw [coneOfHom_fac]
    dsimp [Cone.extend]; cases s; 

Proof state:
case h.e_8.h.mk
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
pt✝ : C
π✝ : (const J).obj pt✝ ⟶ F
m : { pt := pt✝, π := π✝ }.pt ⟶ (limitCone h).pt
w : ∀ (j : J), m ≫ (limitCone h).π.app j = { pt := pt✝, π := π✝ }.π.app j
⊢ { pt := { pt := pt✝, π := π✝ }.pt, π := (const J).map m ≫ (limitCone h).π } = { pt := pt✝, π := π✝ }

Next tactic:
congr with j
/-- If `F.cones` is representable, then the cone corresponding to the identity morphism on
the representing object is a limit cone.
-/
def ofNatIso {X : C} (h : yoneda.obj X ⋙ uliftFunctor.{u₁} ≅ F.cones) : IsLimit (limitCone h)
    where
  lift s := homOfCone h s
  fac s j := by
    have h := cone_fac h s
    cases s
    injection h with h₁ h₂
    simp only [heq_iff_eq] at h₂
    conv_rhs => rw [← h₂]; rfl
  uniq s m w := by
    rw [← homOfCone_coneOfHom h m]
    congr
    rw [coneOfHom_fac]
    dsimp [Cone.extend]; cases s; congr with j; 

Proof state:
case h.e_8.h.mk.e_π.w.h
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cone F
X : C
h : yoneda.obj X ⋙ uliftFunctor.{u₁, v₃} ≅ Functor.cones F
pt✝ : C
π✝ : (const J).obj pt✝ ⟶ F
m : { pt := pt✝, π := π✝ }.pt ⟶ (limitCone h).pt
w : ∀ (j : J), m ≫ (limitCone h).π.app j = { pt := pt✝, π := π✝ }.π.app j
j : J
⊢ ((const J).map m ≫ (limitCone h).π).app j = π✝.app j

Next tactic:
exact w j
instance subsingleton {t : Cocone F} : Subsingleton (IsColimit t) :=
  ⟨by 

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cocone F
⊢ ∀ (a b : IsColimit t), a = b

Next tactic:
intro P Q
instance subsingleton {t : Cocone F} : Subsingleton (IsColimit t) :=
  ⟨by intro P Q; 

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cocone F
P Q : IsColimit t
⊢ P = Q

Next tactic:
cases P
instance subsingleton {t : Cocone F} : Subsingleton (IsColimit t) :=
  ⟨by intro P Q; cases P; 

Proof state:
case mk
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cocone F
Q : IsColimit t
desc✝ : (s : Cocone F) → t.pt ⟶ s.pt
fac✝ : ∀ (s : Cocone F) (j : J), t.ι.app j ≫ desc✝ s = s.ι.app j
uniq✝ : ∀ (s : Cocone F) (m : t.pt ⟶ s.pt), (∀ (j : J), t.ι.app j ≫ m = s.ι.app j) → m = desc✝ s
⊢ mk desc✝ = Q

Next tactic:
cases Q
instance subsingleton {t : Cocone F} : Subsingleton (IsColimit t) :=
  ⟨by intro P Q; cases P; cases Q; 

Proof state:
case mk.mk
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cocone F
desc✝¹ : (s : Cocone F) → t.pt ⟶ s.pt
fac✝¹ : ∀ (s : Cocone F) (j : J), t.ι.app j ≫ desc✝¹ s = s.ι.app j
uniq✝¹ : ∀ (s : Cocone F) (m : t.pt ⟶ s.pt), (∀ (j : J), t.ι.app j ≫ m = s.ι.app j) → m = desc✝¹ s
desc✝ : (s : Cocone F) → t.pt ⟶ s.pt
fac✝ : ∀ (s : Cocone F) (j : J), t.ι.app j ≫ desc✝ s = s.ι.app j
uniq✝ : ∀ (s : Cocone F) (m : t.pt ⟶ s.pt), (∀ (j : J), t.ι.app j ≫ m = s.ι.app j) → m = desc✝ s
⊢ mk desc✝¹ = mk desc✝

Next tactic:
congr
instance subsingleton {t : Cocone F} : Subsingleton (IsColimit t) :=
  ⟨by intro P Q; cases P; cases Q; congr; 

Proof state:
case mk.mk.e_desc
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cocone F
desc✝¹ : (s : Cocone F) → t.pt ⟶ s.pt
fac✝¹ : ∀ (s : Cocone F) (j : J), t.ι.app j ≫ desc✝¹ s = s.ι.app j
uniq✝¹ : ∀ (s : Cocone F) (m : t.pt ⟶ s.pt), (∀ (j : J), t.ι.app j ≫ m = s.ι.app j) → m = desc✝¹ s
desc✝ : (s : Cocone F) → t.pt ⟶ s.pt
fac✝ : ∀ (s : Cocone F) (j : J), t.ι.app j ≫ desc✝ s = s.ι.app j
uniq✝ : ∀ (s : Cocone F) (m : t.pt ⟶ s.pt), (∀ (j : J), t.ι.app j ≫ m = s.ι.app j) → m = desc✝ s
⊢ desc✝¹ = desc✝

Next tactic:
aesop_cat
theorem uniq_cocone_morphism {s t : Cocone F} (h : IsColimit t) {f f' : t ⟶ s} : f = f' :=
  have : ∀ {g : t ⟶ s}, g = h.descCoconeMorphism s := by
    

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
s t : Cocone F
h : IsColimit t
f f' : t ⟶ s
⊢ ∀ {g : t ⟶ s}, g = descCoconeMorphism h s

Next tactic:
intro g
theorem uniq_cocone_morphism {s t : Cocone F} (h : IsColimit t) {f f' : t ⟶ s} : f = f' :=
  have : ∀ {g : t ⟶ s}, g = h.descCoconeMorphism s := by
    intro g; 

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
s t : Cocone F
h : IsColimit t
f f' g : t ⟶ s
⊢ g = descCoconeMorphism h s

Next tactic:
ext
theorem uniq_cocone_morphism {s t : Cocone F} (h : IsColimit t) {f f' : t ⟶ s} : f = f' :=
  have : ∀ {g : t ⟶ s}, g = h.descCoconeMorphism s := by
    intro g; ext; 

Proof state:
case w
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
s t : Cocone F
h : IsColimit t
f f' g : t ⟶ s
⊢ g.hom = (descCoconeMorphism h s).hom

Next tactic:
exact h.uniq _ _ g.w
/-- Noncomputably make a colimit cocone from the existence of unique factorizations. -/
def ofExistsUnique {t : Cocone F}
    (ht : ∀ s : Cocone F, ∃! d : t.pt ⟶ s.pt, ∀ j, t.ι.app j ≫ d = s.ι.app j) : IsColimit t := by
  

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cocone F
ht : ∀ (s : Cocone F), ∃! d, ∀ (j : J), t.ι.app j ≫ d = s.ι.app j
⊢ IsColimit t

Next tactic:
choose s hs hs' using ht
/-- Noncomputably make a colimit cocone from the existence of unique factorizations. -/
def ofExistsUnique {t : Cocone F}
    (ht : ∀ s : Cocone F, ∃! d : t.pt ⟶ s.pt, ∀ j, t.ι.app j ≫ d = s.ι.app j) : IsColimit t := by
  choose s hs hs' using ht
  

Proof state:
J : Type u₁
inst✝² : Category.{v₁, u₁} J
K : Type u₂
inst✝¹ : Category.{v₂, u₂} K
C : Type u₃
inst✝ : Category.{v₃, u₃} C
F : J ⥤ C
t : Cocone F
s : (s : Cocone F) → t.pt ⟶ s.pt
hs : ∀ (s_1 : Cocone F), (fun d => ∀ (j : J), t.ι.app j ≫ d = s_1.ι.app j) (s s_1)
hs' : ∀ (s_1 : Cocone F) (y : t.pt ⟶ s_1.pt), (fun d => ∀ (j : J), t.ι.app j ≫ d = s_1.ι.app j) y → y = s s_1
⊢ IsColimit t

Next tactic:
exact ⟨s, hs, hs'⟩