l3lab/ntp-mathlib huggingface dataset:
/-- A category with finite biproducts has a zero object. -/
instance (priority := 100) hasZeroObject_of_hasFiniteBiproducts [HasFiniteBiproducts C] :
    HasZeroObject C := by
  refine' ⟨⟨biproduct Empty.elim, fun X => ⟨⟨⟨0⟩, _⟩⟩, fun X => ⟨⟨⟨0⟩, _⟩⟩⟩⟩
  · intro a; apply biproduct.hom_ext'; 

Proof state:
case refine'_1.w
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
inst✝ : HasFiniteBiproducts C
X : C
a : ⨁ Empty.elim ⟶ X
⊢ ∀ (j : Empty), biproduct.ι Empty.elim j ≫ a = biproduct.ι Empty.elim j ≫ default

Next tactic:
simp
/-- A category with finite biproducts has a zero object. -/
instance (priority := 100) hasZeroObject_of_hasFiniteBiproducts [HasFiniteBiproducts C] :
    HasZeroObject C := by
  refine' ⟨⟨biproduct Empty.elim, fun X => ⟨⟨⟨0⟩, _⟩⟩, fun X => ⟨⟨⟨0⟩, _⟩⟩⟩⟩
  · intro a; apply biproduct.hom_ext'; simp
  · 

Proof state:
case refine'_2
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
inst✝ : HasFiniteBiproducts C
X : C
⊢ ∀ (a : X ⟶ ⨁ Empty.elim), a = default

Next tactic:
intro a
/-- A category with finite biproducts has a zero object. -/
instance (priority := 100) hasZeroObject_of_hasFiniteBiproducts [HasFiniteBiproducts C] :
    HasZeroObject C := by
  refine' ⟨⟨biproduct Empty.elim, fun X => ⟨⟨⟨0⟩, _⟩⟩, fun X => ⟨⟨⟨0⟩, _⟩⟩⟩⟩
  · intro a; apply biproduct.hom_ext'; simp
  · intro a; 

Proof state:
case refine'_2
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
inst✝ : HasFiniteBiproducts C
X : C
a : X ⟶ ⨁ Empty.elim
⊢ a = default

Next tactic:
apply biproduct.hom_ext
/-- A category with finite biproducts has a zero object. -/
instance (priority := 100) hasZeroObject_of_hasFiniteBiproducts [HasFiniteBiproducts C] :
    HasZeroObject C := by
  refine' ⟨⟨biproduct Empty.elim, fun X => ⟨⟨⟨0⟩, _⟩⟩, fun X => ⟨⟨⟨0⟩, _⟩⟩⟩⟩
  · intro a; apply biproduct.hom_ext'; simp
  · intro a; apply biproduct.hom_ext; 

Proof state:
case refine'_2.w
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
inst✝ : HasFiniteBiproducts C
X : C
a : X ⟶ ⨁ Empty.elim
⊢ ∀ (j : Empty), a ≫ biproduct.π Empty.elim j = default ≫ biproduct.π Empty.elim j

Next tactic:
simp
attribute [local simp] eq_iff_true_of_subsingleton in
/-- The limit bicone for the biproduct over an index type with exactly one term. -/
@[simps]
def limitBiconeOfUnique : LimitBicone f where
  bicone :=
    { pt := f default
      π := fun j => eqToHom (by 

Proof state:
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
inst✝ : Unique J
f : J → C
j : J
⊢ f default = f j

Next tactic:
congr
attribute [local simp] eq_iff_true_of_subsingleton in
/-- The limit bicone for the biproduct over an index type with exactly one term. -/
@[simps]
def limitBiconeOfUnique : LimitBicone f where
  bicone :=
    { pt := f default
      π := fun j => eqToHom (by congr; 

Proof state:
case e_a
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
inst✝ : Unique J
f : J → C
j : J
⊢ default = j

Next tactic:
rw [← Unique.uniq]
attribute [local simp] eq_iff_true_of_subsingleton in
/-- The limit bicone for the biproduct over an index type with exactly one term. -/
@[simps]
def limitBiconeOfUnique : LimitBicone f where
  bicone :=
    { pt := f default
      π := fun j => eqToHom (by congr; rw [← Unique.uniq] )
      ι := fun j => eqToHom (by 

Proof state:
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
inst✝ : Unique J
f : J → C
j : J
⊢ f j = f default

Next tactic:
congr
attribute [local simp] eq_iff_true_of_subsingleton in
/-- The limit bicone for the biproduct over an index type with exactly one term. -/
@[simps]
def limitBiconeOfUnique : LimitBicone f where
  bicone :=
    { pt := f default
      π := fun j => eqToHom (by congr; rw [← Unique.uniq] )
      ι := fun j => eqToHom (by congr; 

Proof state:
case e_a
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
inst✝ : Unique J
f : J → C
j : J
⊢ j = default

Next tactic:
rw [← Unique.uniq]
/-- Convert a `BinaryBicone` into a `Bicone` over a pair. -/
@[simps]
def toBicone {X Y : C} (b : BinaryBicone X Y) : Bicone (pairFunction X Y) where
  pt := b.pt
  π j := WalkingPair.casesOn j b.fst b.snd
  ι j := WalkingPair.casesOn j b.inl b.inr
  ι_π j j' := by
    

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
j j' : WalkingPair
⊢ (fun j => WalkingPair.casesOn j b.inl b.inr) j ≫ (fun j => WalkingPair.casesOn j b.fst b.snd) j' =
    if h : j = j' then eqToHom (_ : pairFunction X Y j = pairFunction X Y j') else 0

Next tactic:
rcases j with ⟨⟩
/-- Convert a `BinaryBicone` into a `Bicone` over a pair. -/
@[simps]
def toBicone {X Y : C} (b : BinaryBicone X Y) : Bicone (pairFunction X Y) where
  pt := b.pt
  π j := WalkingPair.casesOn j b.fst b.snd
  ι j := WalkingPair.casesOn j b.inl b.inr
  ι_π j j' := by
    rcases j with ⟨⟩ <;> 

Proof state:
case left
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
j' : WalkingPair
⊢ (fun j => WalkingPair.casesOn j b.inl b.inr) WalkingPair.left ≫ (fun j => WalkingPair.casesOn j b.fst b.snd) j' =
    if h : WalkingPair.left = j' then eqToHom (_ : pairFunction X Y WalkingPair.left = pairFunction X Y j') else 0

Next tactic:
rcases j' with ⟨⟩
/-- Convert a `BinaryBicone` into a `Bicone` over a pair. -/
@[simps]
def toBicone {X Y : C} (b : BinaryBicone X Y) : Bicone (pairFunction X Y) where
  pt := b.pt
  π j := WalkingPair.casesOn j b.fst b.snd
  ι j := WalkingPair.casesOn j b.inl b.inr
  ι_π j j' := by
    rcases j with ⟨⟩ <;> 

Proof state:
case right
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
j' : WalkingPair
⊢ (fun j => WalkingPair.casesOn j b.inl b.inr) WalkingPair.right ≫ (fun j => WalkingPair.casesOn j b.fst b.snd) j' =
    if h : WalkingPair.right = j' then eqToHom (_ : pairFunction X Y WalkingPair.right = pairFunction X Y j') else 0

Next tactic:
rcases j' with ⟨⟩
/-- Convert a `BinaryBicone` into a `Bicone` over a pair. -/
@[simps]
def toBicone {X Y : C} (b : BinaryBicone X Y) : Bicone (pairFunction X Y) where
  pt := b.pt
  π j := WalkingPair.casesOn j b.fst b.snd
  ι j := WalkingPair.casesOn j b.inl b.inr
  ι_π j j' := by
    rcases j with ⟨⟩ <;> rcases j' with ⟨⟩ <;> 

Proof state:
case left.left
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
⊢ (fun j => WalkingPair.casesOn j b.inl b.inr) WalkingPair.left ≫
      (fun j => WalkingPair.casesOn j b.fst b.snd) WalkingPair.left =
    if h : WalkingPair.left = WalkingPair.left then
      eqToHom (_ : pairFunction X Y WalkingPair.left = pairFunction X Y WalkingPair.left)
    else 0

Next tactic:
simp
/-- Convert a `BinaryBicone` into a `Bicone` over a pair. -/
@[simps]
def toBicone {X Y : C} (b : BinaryBicone X Y) : Bicone (pairFunction X Y) where
  pt := b.pt
  π j := WalkingPair.casesOn j b.fst b.snd
  ι j := WalkingPair.casesOn j b.inl b.inr
  ι_π j j' := by
    rcases j with ⟨⟩ <;> rcases j' with ⟨⟩ <;> 

Proof state:
case left.right
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
⊢ (fun j => WalkingPair.casesOn j b.inl b.inr) WalkingPair.left ≫
      (fun j => WalkingPair.casesOn j b.fst b.snd) WalkingPair.right =
    if h : WalkingPair.left = WalkingPair.right then
      eqToHom (_ : pairFunction X Y WalkingPair.left = pairFunction X Y WalkingPair.right)
    else 0

Next tactic:
simp
/-- Convert a `BinaryBicone` into a `Bicone` over a pair. -/
@[simps]
def toBicone {X Y : C} (b : BinaryBicone X Y) : Bicone (pairFunction X Y) where
  pt := b.pt
  π j := WalkingPair.casesOn j b.fst b.snd
  ι j := WalkingPair.casesOn j b.inl b.inr
  ι_π j j' := by
    rcases j with ⟨⟩ <;> rcases j' with ⟨⟩ <;> 

Proof state:
case right.left
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
⊢ (fun j => WalkingPair.casesOn j b.inl b.inr) WalkingPair.right ≫
      (fun j => WalkingPair.casesOn j b.fst b.snd) WalkingPair.left =
    if h : WalkingPair.right = WalkingPair.left then
      eqToHom (_ : pairFunction X Y WalkingPair.right = pairFunction X Y WalkingPair.left)
    else 0

Next tactic:
simp
/-- Convert a `BinaryBicone` into a `Bicone` over a pair. -/
@[simps]
def toBicone {X Y : C} (b : BinaryBicone X Y) : Bicone (pairFunction X Y) where
  pt := b.pt
  π j := WalkingPair.casesOn j b.fst b.snd
  ι j := WalkingPair.casesOn j b.inl b.inr
  ι_π j j' := by
    rcases j with ⟨⟩ <;> rcases j' with ⟨⟩ <;> 

Proof state:
case right.right
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
⊢ (fun j => WalkingPair.casesOn j b.inl b.inr) WalkingPair.right ≫
      (fun j => WalkingPair.casesOn j b.fst b.snd) WalkingPair.right =
    if h : WalkingPair.right = WalkingPair.right then
      eqToHom (_ : pairFunction X Y WalkingPair.right = pairFunction X Y WalkingPair.right)
    else 0

Next tactic:
simp
/-- A binary bicone is a limit cone if and only if the corresponding bicone is a limit cone. -/
def toBiconeIsLimit {X Y : C} (b : BinaryBicone X Y) :
    IsLimit b.toBicone.toCone ≃ IsLimit b.toCone :=
  IsLimit.equivIsoLimit <|
    Cones.ext (Iso.refl _) fun j => by
      

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
j : Discrete WalkingPair
⊢ (Bicone.toCone (toBicone b)).π.app j = (Iso.refl (Bicone.toCone (toBicone b)).pt).hom ≫ (toCone b).π.app j

Next tactic:
cases' j with as
/-- A binary bicone is a limit cone if and only if the corresponding bicone is a limit cone. -/
def toBiconeIsLimit {X Y : C} (b : BinaryBicone X Y) :
    IsLimit b.toBicone.toCone ≃ IsLimit b.toCone :=
  IsLimit.equivIsoLimit <|
    Cones.ext (Iso.refl _) fun j => by
      cases' j with as; 

Proof state:
case mk
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
as : WalkingPair
⊢ (Bicone.toCone (toBicone b)).π.app { as := as } =
    (Iso.refl (Bicone.toCone (toBicone b)).pt).hom ≫ (toCone b).π.app { as := as }

Next tactic:
cases as
/-- A binary bicone is a limit cone if and only if the corresponding bicone is a limit cone. -/
def toBiconeIsLimit {X Y : C} (b : BinaryBicone X Y) :
    IsLimit b.toBicone.toCone ≃ IsLimit b.toCone :=
  IsLimit.equivIsoLimit <|
    Cones.ext (Iso.refl _) fun j => by
      cases' j with as; cases as <;> 

Proof state:
case mk.left
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
⊢ (Bicone.toCone (toBicone b)).π.app { as := WalkingPair.left } =
    (Iso.refl (Bicone.toCone (toBicone b)).pt).hom ≫ (toCone b).π.app { as := WalkingPair.left }

Next tactic:
simp
/-- A binary bicone is a limit cone if and only if the corresponding bicone is a limit cone. -/
def toBiconeIsLimit {X Y : C} (b : BinaryBicone X Y) :
    IsLimit b.toBicone.toCone ≃ IsLimit b.toCone :=
  IsLimit.equivIsoLimit <|
    Cones.ext (Iso.refl _) fun j => by
      cases' j with as; cases as <;> 

Proof state:
case mk.right
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
⊢ (Bicone.toCone (toBicone b)).π.app { as := WalkingPair.right } =
    (Iso.refl (Bicone.toCone (toBicone b)).pt).hom ≫ (toCone b).π.app { as := WalkingPair.right }

Next tactic:
simp
/-- A binary bicone is a colimit cocone if and only if the corresponding bicone is a colimit
    cocone. -/
def toBiconeIsColimit {X Y : C} (b : BinaryBicone X Y) :
    IsColimit b.toBicone.toCocone ≃ IsColimit b.toCocone :=
  IsColimit.equivIsoColimit <|
    Cocones.ext (Iso.refl _) fun j => by
      

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
j : Discrete WalkingPair
⊢ (Bicone.toCocone (toBicone b)).ι.app j ≫ (Iso.refl (Bicone.toCocone (toBicone b)).pt).hom = (toCocone b).ι.app j

Next tactic:
cases' j with as
/-- A binary bicone is a colimit cocone if and only if the corresponding bicone is a colimit
    cocone. -/
def toBiconeIsColimit {X Y : C} (b : BinaryBicone X Y) :
    IsColimit b.toBicone.toCocone ≃ IsColimit b.toCocone :=
  IsColimit.equivIsoColimit <|
    Cocones.ext (Iso.refl _) fun j => by
      cases' j with as; 

Proof state:
case mk
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
as : WalkingPair
⊢ (Bicone.toCocone (toBicone b)).ι.app { as := as } ≫ (Iso.refl (Bicone.toCocone (toBicone b)).pt).hom =
    (toCocone b).ι.app { as := as }

Next tactic:
cases as
/-- A binary bicone is a colimit cocone if and only if the corresponding bicone is a colimit
    cocone. -/
def toBiconeIsColimit {X Y : C} (b : BinaryBicone X Y) :
    IsColimit b.toBicone.toCocone ≃ IsColimit b.toCocone :=
  IsColimit.equivIsoColimit <|
    Cocones.ext (Iso.refl _) fun j => by
      cases' j with as; cases as <;> 

Proof state:
case mk.left
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
⊢ (Bicone.toCocone (toBicone b)).ι.app { as := WalkingPair.left } ≫ (Iso.refl (Bicone.toCocone (toBicone b)).pt).hom =
    (toCocone b).ι.app { as := WalkingPair.left }

Next tactic:
simp
/-- A binary bicone is a colimit cocone if and only if the corresponding bicone is a colimit
    cocone. -/
def toBiconeIsColimit {X Y : C} (b : BinaryBicone X Y) :
    IsColimit b.toBicone.toCocone ≃ IsColimit b.toCocone :=
  IsColimit.equivIsoColimit <|
    Cocones.ext (Iso.refl _) fun j => by
      cases' j with as; cases as <;> 

Proof state:
case mk.right
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
b : BinaryBicone X Y
⊢ (Bicone.toCocone (toBicone b)).ι.app { as := WalkingPair.right } ≫ (Iso.refl (Bicone.toCocone (toBicone b)).pt).hom =
    (toCocone b).ι.app { as := WalkingPair.right }

Next tactic:
simp
/-- Convert a `Bicone` over a function on `WalkingPair` to a BinaryBicone. -/
@[simps]
def toBinaryBicone {X Y : C} (b : Bicone (pairFunction X Y)) : BinaryBicone X Y where
  pt := b.pt
  fst := b.π WalkingPair.left
  snd := b.π WalkingPair.right
  inl := b.ι WalkingPair.left
  inr := b.ι WalkingPair.right
  inl_fst := by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
⊢ ι b WalkingPair.left ≫ π b WalkingPair.left = 𝟙 X

Next tactic:
simp [Bicone.ι_π]
/-- Convert a `Bicone` over a function on `WalkingPair` to a BinaryBicone. -/
@[simps]
def toBinaryBicone {X Y : C} (b : Bicone (pairFunction X Y)) : BinaryBicone X Y where
  pt := b.pt
  fst := b.π WalkingPair.left
  snd := b.π WalkingPair.right
  inl := b.ι WalkingPair.left
  inr := b.ι WalkingPair.right
  inl_fst := by simp [Bicone.ι_π]
  inr_fst := by simp [Bicone.ι_π]
  inl_snd := by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
⊢ ι b WalkingPair.left ≫ π b WalkingPair.right = 0

Next tactic:
simp [Bicone.ι_π]
/-- Convert a `Bicone` over a function on `WalkingPair` to a BinaryBicone. -/
@[simps]
def toBinaryBicone {X Y : C} (b : Bicone (pairFunction X Y)) : BinaryBicone X Y where
  pt := b.pt
  fst := b.π WalkingPair.left
  snd := b.π WalkingPair.right
  inl := b.ι WalkingPair.left
  inr := b.ι WalkingPair.right
  inl_fst := by simp [Bicone.ι_π]
  inr_fst := by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
⊢ ι b WalkingPair.right ≫ π b WalkingPair.left = 0

Next tactic:
simp [Bicone.ι_π]
/-- Convert a `Bicone` over a function on `WalkingPair` to a BinaryBicone. -/
@[simps]
def toBinaryBicone {X Y : C} (b : Bicone (pairFunction X Y)) : BinaryBicone X Y where
  pt := b.pt
  fst := b.π WalkingPair.left
  snd := b.π WalkingPair.right
  inl := b.ι WalkingPair.left
  inr := b.ι WalkingPair.right
  inl_fst := by simp [Bicone.ι_π]
  inr_fst := by simp [Bicone.ι_π]
  inl_snd := by simp [Bicone.ι_π]
  inr_snd := by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
⊢ ι b WalkingPair.right ≫ π b WalkingPair.right = 𝟙 Y

Next tactic:
simp [Bicone.ι_π]
/-- A bicone over a pair is a limit cone if and only if the corresponding binary bicone is a limit
    cone.  -/
def toBinaryBiconeIsLimit {X Y : C} (b : Bicone (pairFunction X Y)) :
    IsLimit b.toBinaryBicone.toCone ≃ IsLimit b.toCone :=
  IsLimit.equivIsoLimit <| Cones.ext (Iso.refl _) fun j => by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
j : Discrete WalkingPair
⊢ (BinaryBicone.toCone (toBinaryBicone b)).π.app j =
    (Iso.refl (BinaryBicone.toCone (toBinaryBicone b)).pt).hom ≫ (toCone b).π.app j

Next tactic:
rcases j with ⟨⟨⟩⟩
/-- A bicone over a pair is a limit cone if and only if the corresponding binary bicone is a limit
    cone.  -/
def toBinaryBiconeIsLimit {X Y : C} (b : Bicone (pairFunction X Y)) :
    IsLimit b.toBinaryBicone.toCone ≃ IsLimit b.toCone :=
  IsLimit.equivIsoLimit <| Cones.ext (Iso.refl _) fun j => by rcases j with ⟨⟨⟩⟩ <;> 

Proof state:
case mk.left
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
⊢ (BinaryBicone.toCone (toBinaryBicone b)).π.app { as := WalkingPair.left } =
    (Iso.refl (BinaryBicone.toCone (toBinaryBicone b)).pt).hom ≫ (toCone b).π.app { as := WalkingPair.left }

Next tactic:
simp
/-- A bicone over a pair is a limit cone if and only if the corresponding binary bicone is a limit
    cone.  -/
def toBinaryBiconeIsLimit {X Y : C} (b : Bicone (pairFunction X Y)) :
    IsLimit b.toBinaryBicone.toCone ≃ IsLimit b.toCone :=
  IsLimit.equivIsoLimit <| Cones.ext (Iso.refl _) fun j => by rcases j with ⟨⟨⟩⟩ <;> 

Proof state:
case mk.right
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
⊢ (BinaryBicone.toCone (toBinaryBicone b)).π.app { as := WalkingPair.right } =
    (Iso.refl (BinaryBicone.toCone (toBinaryBicone b)).pt).hom ≫ (toCone b).π.app { as := WalkingPair.right }

Next tactic:
simp
/-- A bicone over a pair is a colimit cocone if and only if the corresponding binary bicone is a
    colimit cocone. -/
def toBinaryBiconeIsColimit {X Y : C} (b : Bicone (pairFunction X Y)) :
    IsColimit b.toBinaryBicone.toCocone ≃ IsColimit b.toCocone :=
  IsColimit.equivIsoColimit <| Cocones.ext (Iso.refl _) fun j => by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
j : Discrete WalkingPair
⊢ (BinaryBicone.toCocone (toBinaryBicone b)).ι.app j ≫ (Iso.refl (BinaryBicone.toCocone (toBinaryBicone b)).pt).hom =
    (toCocone b).ι.app j

Next tactic:
rcases j with ⟨⟨⟩⟩
/-- A bicone over a pair is a colimit cocone if and only if the corresponding binary bicone is a
    colimit cocone. -/
def toBinaryBiconeIsColimit {X Y : C} (b : Bicone (pairFunction X Y)) :
    IsColimit b.toBinaryBicone.toCocone ≃ IsColimit b.toCocone :=
  IsColimit.equivIsoColimit <| Cocones.ext (Iso.refl _) fun j => by rcases j with ⟨⟨⟩⟩ <;> 

Proof state:
case mk.left
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
⊢ (BinaryBicone.toCocone (toBinaryBicone b)).ι.app { as := WalkingPair.left } ≫
      (Iso.refl (BinaryBicone.toCocone (toBinaryBicone b)).pt).hom =
    (toCocone b).ι.app { as := WalkingPair.left }

Next tactic:
simp
/-- A bicone over a pair is a colimit cocone if and only if the corresponding binary bicone is a
    colimit cocone. -/
def toBinaryBiconeIsColimit {X Y : C} (b : Bicone (pairFunction X Y)) :
    IsColimit b.toBinaryBicone.toCocone ≃ IsColimit b.toCocone :=
  IsColimit.equivIsoColimit <| Cocones.ext (Iso.refl _) fun j => by rcases j with ⟨⟨⟩⟩ <;> 

Proof state:
case mk.right
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : Bicone (pairFunction X Y)
⊢ (BinaryBicone.toCocone (toBinaryBicone b)).ι.app { as := WalkingPair.right } ≫
      (Iso.refl (BinaryBicone.toCocone (toBinaryBicone b)).pt).hom =
    (toCocone b).ι.app { as := WalkingPair.right }

Next tactic:
simp
/-- A binary bicone is a bilimit bicone if and only if the corresponding bicone is a bilimit. -/
def BinaryBicone.toBiconeIsBilimit {X Y : C} (b : BinaryBicone X Y) :
    b.toBicone.IsBilimit ≃ b.IsBilimit where
  toFun h := ⟨b.toBiconeIsLimit h.isLimit, b.toBiconeIsColimit h.isColimit⟩
  invFun h := ⟨b.toBiconeIsLimit.symm h.isLimit, b.toBiconeIsColimit.symm h.isColimit⟩
  left_inv := fun ⟨h, h'⟩ => by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : BinaryBicone X Y
x✝ : Bicone.IsBilimit (toBicone b)
h : IsLimit (Bicone.toCone (toBicone b))
h' : IsColimit (Bicone.toCocone (toBicone b))
⊢ (fun h => { isLimit := (toBiconeIsLimit b).symm h.isLimit, isColimit := (toBiconeIsColimit b).symm h.isColimit })
      ((fun h => { isLimit := (toBiconeIsLimit b) h.isLimit, isColimit := (toBiconeIsColimit b) h.isColimit })
        { isLimit := h, isColimit := h' }) =
    { isLimit := h, isColimit := h' }

Next tactic:
dsimp only
/-- A binary bicone is a bilimit bicone if and only if the corresponding bicone is a bilimit. -/
def BinaryBicone.toBiconeIsBilimit {X Y : C} (b : BinaryBicone X Y) :
    b.toBicone.IsBilimit ≃ b.IsBilimit where
  toFun h := ⟨b.toBiconeIsLimit h.isLimit, b.toBiconeIsColimit h.isColimit⟩
  invFun h := ⟨b.toBiconeIsLimit.symm h.isLimit, b.toBiconeIsColimit.symm h.isColimit⟩
  left_inv := fun ⟨h, h'⟩ => by dsimp only; 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : BinaryBicone X Y
x✝ : Bicone.IsBilimit (toBicone b)
h : IsLimit (Bicone.toCone (toBicone b))
h' : IsColimit (Bicone.toCocone (toBicone b))
⊢ { isLimit := (toBiconeIsLimit b).symm ((toBiconeIsLimit b) h),
      isColimit := (toBiconeIsColimit b).symm ((toBiconeIsColimit b) h') } =
    { isLimit := h, isColimit := h' }

Next tactic:
simp
/-- A binary bicone is a bilimit bicone if and only if the corresponding bicone is a bilimit. -/
def BinaryBicone.toBiconeIsBilimit {X Y : C} (b : BinaryBicone X Y) :
    b.toBicone.IsBilimit ≃ b.IsBilimit where
  toFun h := ⟨b.toBiconeIsLimit h.isLimit, b.toBiconeIsColimit h.isColimit⟩
  invFun h := ⟨b.toBiconeIsLimit.symm h.isLimit, b.toBiconeIsColimit.symm h.isColimit⟩
  left_inv := fun ⟨h, h'⟩ => by dsimp only; simp
  right_inv := fun ⟨h, h'⟩ => by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : BinaryBicone X Y
x✝ : IsBilimit b
h : IsLimit (toCone b)
h' : IsColimit (toCocone b)
⊢ (fun h => { isLimit := (toBiconeIsLimit b) h.isLimit, isColimit := (toBiconeIsColimit b) h.isColimit })
      ((fun h => { isLimit := (toBiconeIsLimit b).symm h.isLimit, isColimit := (toBiconeIsColimit b).symm h.isColimit })
        { isLimit := h, isColimit := h' }) =
    { isLimit := h, isColimit := h' }

Next tactic:
dsimp only
/-- A binary bicone is a bilimit bicone if and only if the corresponding bicone is a bilimit. -/
def BinaryBicone.toBiconeIsBilimit {X Y : C} (b : BinaryBicone X Y) :
    b.toBicone.IsBilimit ≃ b.IsBilimit where
  toFun h := ⟨b.toBiconeIsLimit h.isLimit, b.toBiconeIsColimit h.isColimit⟩
  invFun h := ⟨b.toBiconeIsLimit.symm h.isLimit, b.toBiconeIsColimit.symm h.isColimit⟩
  left_inv := fun ⟨h, h'⟩ => by dsimp only; simp
  right_inv := fun ⟨h, h'⟩ => by dsimp only; 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
X Y : C
b : BinaryBicone X Y
x✝ : IsBilimit b
h : IsLimit (toCone b)
h' : IsColimit (toCocone b)
⊢ { isLimit := (toBiconeIsLimit b) ((toBiconeIsLimit b).symm h),
      isColimit := (toBiconeIsColimit b) ((toBiconeIsColimit b).symm h') } =
    { isLimit := h, isColimit := h' }

Next tactic:
simp