l3lab/ntp-mathlib huggingface dataset:
/-- If a cospan is the pushout cospan under the initial object, then it is a binary coproduct. -/
def isBinaryCoproductOfIsInitialIsPushout (F : Discrete WalkingPair ⥤ C) (c : Cocone F) {X : C}
    (hX : IsInitial X) (f : X ⟶ F.obj ⟨WalkingPair.left⟩) (g : X ⟶ F.obj ⟨WalkingPair.right⟩)
    (hc :
      IsColimit
        (PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩) (c.ι.app ⟨WalkingPair.right⟩ : _) <|
          hX.hom_ext (f ≫ _) (g ≫ _))) :
    IsColimit c
    where
  desc s :=
    hc.desc
      (PushoutCocone.mk (s.ι.app ⟨WalkingPair.left⟩) (s.ι.app ⟨WalkingPair.right⟩) (hX.hom_ext _ _))
  fac s j :=
    Discrete.casesOn j fun j =>
      WalkingPair.casesOn j (hc.fac _ WalkingSpan.left) (hc.fac _ WalkingSpan.right)
  uniq s m J := by
    let c' :=
      PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩ ≫ m) (c.ι.app ⟨WalkingPair.right⟩ ≫ m)
        (hX.hom_ext (f ≫ _) (g ≫ _))
    dsimp; rw [← J, ← J]
    apply hc.hom_ext
    

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F✝ : C ⥤ D
F : Discrete WalkingPair ⥤ C
c : Cocone F
X : C
hX : IsInitial X
f : X ⟶ F.obj { as := WalkingPair.left }
g : X ⟶ F.obj { as := WalkingPair.right }
hc :
  IsColimit
    (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
      (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right }))
s : Cocone F
m : c.pt ⟶ s.pt
J : ∀ (j : Discrete WalkingPair), c.ι.app j ≫ m = s.ι.app j
c' : PushoutCocone f g :=
  PushoutCocone.mk (c.ι.app { as := WalkingPair.left } ≫ m) (c.ι.app { as := WalkingPair.right } ≫ m)
    (_ : f ≫ c.ι.app { as := WalkingPair.left } ≫ m = g ≫ c.ι.app { as := WalkingPair.right } ≫ m)
⊢ ∀ (j : WalkingSpan),
    (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
                (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right })).ι.app
          j ≫
        m =
      (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
                (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right })).ι.app
          j ≫
        IsColimit.desc hc
          (PushoutCocone.mk (c.ι.app { as := WalkingPair.left } ≫ m) (c.ι.app { as := WalkingPair.right } ≫ m)
            (_ : f ≫ c.ι.app { as := WalkingPair.left } ≫ m = g ≫ c.ι.app { as := WalkingPair.right } ≫ m))

Next tactic:
rintro (_ | (_ | _))
/-- If a cospan is the pushout cospan under the initial object, then it is a binary coproduct. -/
def isBinaryCoproductOfIsInitialIsPushout (F : Discrete WalkingPair ⥤ C) (c : Cocone F) {X : C}
    (hX : IsInitial X) (f : X ⟶ F.obj ⟨WalkingPair.left⟩) (g : X ⟶ F.obj ⟨WalkingPair.right⟩)
    (hc :
      IsColimit
        (PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩) (c.ι.app ⟨WalkingPair.right⟩ : _) <|
          hX.hom_ext (f ≫ _) (g ≫ _))) :
    IsColimit c
    where
  desc s :=
    hc.desc
      (PushoutCocone.mk (s.ι.app ⟨WalkingPair.left⟩) (s.ι.app ⟨WalkingPair.right⟩) (hX.hom_ext _ _))
  fac s j :=
    Discrete.casesOn j fun j =>
      WalkingPair.casesOn j (hc.fac _ WalkingSpan.left) (hc.fac _ WalkingSpan.right)
  uniq s m J := by
    let c' :=
      PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩ ≫ m) (c.ι.app ⟨WalkingPair.right⟩ ≫ m)
        (hX.hom_ext (f ≫ _) (g ≫ _))
    dsimp; rw [← J, ← J]
    apply hc.hom_ext
    rintro (_ | (_ | _)) <;>
      

Proof state:
case none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F✝ : C ⥤ D
F : Discrete WalkingPair ⥤ C
c : Cocone F
X : C
hX : IsInitial X
f : X ⟶ F.obj { as := WalkingPair.left }
g : X ⟶ F.obj { as := WalkingPair.right }
hc :
  IsColimit
    (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
      (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right }))
s : Cocone F
m : c.pt ⟶ s.pt
J : ∀ (j : Discrete WalkingPair), c.ι.app j ≫ m = s.ι.app j
c' : PushoutCocone f g :=
  PushoutCocone.mk (c.ι.app { as := WalkingPair.left } ≫ m) (c.ι.app { as := WalkingPair.right } ≫ m)
    (_ : f ≫ c.ι.app { as := WalkingPair.left } ≫ m = g ≫ c.ι.app { as := WalkingPair.right } ≫ m)
⊢ (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
              (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right })).ι.app
        none ≫
      m =
    (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
              (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right })).ι.app
        none ≫
      IsColimit.desc hc
        (PushoutCocone.mk (c.ι.app { as := WalkingPair.left } ≫ m) (c.ι.app { as := WalkingPair.right } ≫ m)
          (_ : f ≫ c.ι.app { as := WalkingPair.left } ≫ m = g ≫ c.ι.app { as := WalkingPair.right } ≫ m))

Next tactic:
simp only [PushoutCocone.mk_ι_app_zero, PushoutCocone.mk_ι_app, Category.assoc]
/-- If a cospan is the pushout cospan under the initial object, then it is a binary coproduct. -/
def isBinaryCoproductOfIsInitialIsPushout (F : Discrete WalkingPair ⥤ C) (c : Cocone F) {X : C}
    (hX : IsInitial X) (f : X ⟶ F.obj ⟨WalkingPair.left⟩) (g : X ⟶ F.obj ⟨WalkingPair.right⟩)
    (hc :
      IsColimit
        (PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩) (c.ι.app ⟨WalkingPair.right⟩ : _) <|
          hX.hom_ext (f ≫ _) (g ≫ _))) :
    IsColimit c
    where
  desc s :=
    hc.desc
      (PushoutCocone.mk (s.ι.app ⟨WalkingPair.left⟩) (s.ι.app ⟨WalkingPair.right⟩) (hX.hom_ext _ _))
  fac s j :=
    Discrete.casesOn j fun j =>
      WalkingPair.casesOn j (hc.fac _ WalkingSpan.left) (hc.fac _ WalkingSpan.right)
  uniq s m J := by
    let c' :=
      PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩ ≫ m) (c.ι.app ⟨WalkingPair.right⟩ ≫ m)
        (hX.hom_ext (f ≫ _) (g ≫ _))
    dsimp; rw [← J, ← J]
    apply hc.hom_ext
    rintro (_ | (_ | _)) <;>
      

Proof state:
case some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F✝ : C ⥤ D
F : Discrete WalkingPair ⥤ C
c : Cocone F
X : C
hX : IsInitial X
f : X ⟶ F.obj { as := WalkingPair.left }
g : X ⟶ F.obj { as := WalkingPair.right }
hc :
  IsColimit
    (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
      (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right }))
s : Cocone F
m : c.pt ⟶ s.pt
J : ∀ (j : Discrete WalkingPair), c.ι.app j ≫ m = s.ι.app j
c' : PushoutCocone f g :=
  PushoutCocone.mk (c.ι.app { as := WalkingPair.left } ≫ m) (c.ι.app { as := WalkingPair.right } ≫ m)
    (_ : f ≫ c.ι.app { as := WalkingPair.left } ≫ m = g ≫ c.ι.app { as := WalkingPair.right } ≫ m)
⊢ (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
              (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right })).ι.app
        (some WalkingPair.left) ≫
      m =
    (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
              (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right })).ι.app
        (some WalkingPair.left) ≫
      IsColimit.desc hc
        (PushoutCocone.mk (c.ι.app { as := WalkingPair.left } ≫ m) (c.ι.app { as := WalkingPair.right } ≫ m)
          (_ : f ≫ c.ι.app { as := WalkingPair.left } ≫ m = g ≫ c.ι.app { as := WalkingPair.right } ≫ m))

Next tactic:
simp only [PushoutCocone.mk_ι_app_zero, PushoutCocone.mk_ι_app, Category.assoc]
/-- If a cospan is the pushout cospan under the initial object, then it is a binary coproduct. -/
def isBinaryCoproductOfIsInitialIsPushout (F : Discrete WalkingPair ⥤ C) (c : Cocone F) {X : C}
    (hX : IsInitial X) (f : X ⟶ F.obj ⟨WalkingPair.left⟩) (g : X ⟶ F.obj ⟨WalkingPair.right⟩)
    (hc :
      IsColimit
        (PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩) (c.ι.app ⟨WalkingPair.right⟩ : _) <|
          hX.hom_ext (f ≫ _) (g ≫ _))) :
    IsColimit c
    where
  desc s :=
    hc.desc
      (PushoutCocone.mk (s.ι.app ⟨WalkingPair.left⟩) (s.ι.app ⟨WalkingPair.right⟩) (hX.hom_ext _ _))
  fac s j :=
    Discrete.casesOn j fun j =>
      WalkingPair.casesOn j (hc.fac _ WalkingSpan.left) (hc.fac _ WalkingSpan.right)
  uniq s m J := by
    let c' :=
      PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩ ≫ m) (c.ι.app ⟨WalkingPair.right⟩ ≫ m)
        (hX.hom_ext (f ≫ _) (g ≫ _))
    dsimp; rw [← J, ← J]
    apply hc.hom_ext
    rintro (_ | (_ | _)) <;>
      

Proof state:
case some.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F✝ : C ⥤ D
F : Discrete WalkingPair ⥤ C
c : Cocone F
X : C
hX : IsInitial X
f : X ⟶ F.obj { as := WalkingPair.left }
g : X ⟶ F.obj { as := WalkingPair.right }
hc :
  IsColimit
    (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
      (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right }))
s : Cocone F
m : c.pt ⟶ s.pt
J : ∀ (j : Discrete WalkingPair), c.ι.app j ≫ m = s.ι.app j
c' : PushoutCocone f g :=
  PushoutCocone.mk (c.ι.app { as := WalkingPair.left } ≫ m) (c.ι.app { as := WalkingPair.right } ≫ m)
    (_ : f ≫ c.ι.app { as := WalkingPair.left } ≫ m = g ≫ c.ι.app { as := WalkingPair.right } ≫ m)
⊢ (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
              (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right })).ι.app
        (some WalkingPair.right) ≫
      m =
    (PushoutCocone.mk (c.ι.app { as := WalkingPair.left }) (c.ι.app { as := WalkingPair.right })
              (_ : f ≫ c.ι.app { as := WalkingPair.left } = g ≫ c.ι.app { as := WalkingPair.right })).ι.app
        (some WalkingPair.right) ≫
      IsColimit.desc hc
        (PushoutCocone.mk (c.ι.app { as := WalkingPair.left } ≫ m) (c.ι.app { as := WalkingPair.right } ≫ m)
          (_ : f ≫ c.ι.app { as := WalkingPair.left } ≫ m = g ≫ c.ι.app { as := WalkingPair.right } ≫ m))

Next tactic:
simp only [PushoutCocone.mk_ι_app_zero, PushoutCocone.mk_ι_app, Category.assoc]
/-- The pushout under the initial object is the coproduct -/
def isCoproductOfIsInitialIsPushout {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W)
    (H₂ : IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _))) :
    IsColimit (BinaryCofan.mk f g) := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g))
⊢ IsColimit (BinaryCofan.mk f g)

Next tactic:
apply isBinaryCoproductOfIsInitialIsPushout _ _ H₁
/-- The pushout under the initial object is the coproduct -/
def isCoproductOfIsInitialIsPushout {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W)
    (H₂ : IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _))) :
    IsColimit (BinaryCofan.mk f g) := by
  apply isBinaryCoproductOfIsInitialIsPushout _ _ H₁
  

Proof state:
case hc
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g))
⊢ IsColimit
    (PushoutCocone.mk ((BinaryCofan.mk f g).ι.app { as := WalkingPair.left })
      ((BinaryCofan.mk f g).ι.app { as := WalkingPair.right })
      (_ :
        ?f ≫ (BinaryCofan.mk f g).ι.app { as := WalkingPair.left } =
          ?g ≫ (BinaryCofan.mk f g).ι.app { as := WalkingPair.right }))
case f
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g))
⊢ W ⟶ (pair X Y).obj { as := WalkingPair.left }
case g
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g))
⊢ W ⟶ (pair X Y).obj { as := WalkingPair.right }

Next tactic:
exact H₂
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
⊢ IsColimit (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g))

Next tactic:
apply PushoutCocone.isColimitAux'
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  apply PushoutCocone.isColimitAux'
  

Proof state:
case create
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
⊢ (s : PushoutCocone h k) →
    { l //
      PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ l = PushoutCocone.inl s ∧
        PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ l = PushoutCocone.inr s ∧
          ∀ {m : (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)).pt ⟶ s.pt},
            PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inl s →
              PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inr s → m = l }

Next tactic:
intro s
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  apply PushoutCocone.isColimitAux'
  intro s
  

Proof state:
case create
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
s : PushoutCocone h k
⊢ { l //
    PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ l = PushoutCocone.inl s ∧
      PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ l = PushoutCocone.inr s ∧
        ∀ {m : (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)).pt ⟶ s.pt},
          PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inl s →
            PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inr s → m = l }

Next tactic:
use H₂.desc (BinaryCofan.mk s.inl s.inr)
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  apply PushoutCocone.isColimitAux'
  intro s
  use H₂.desc (BinaryCofan.mk s.inl s.inr)
  

Proof state:
case property
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
s : PushoutCocone h k
⊢ PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫
        IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s)) =
      PushoutCocone.inl s ∧
    PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫
          IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s)) =
        PushoutCocone.inr s ∧
      ∀ {m : (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)).pt ⟶ s.pt},
        PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inl s →
          PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inr s →
            m = IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s))

Next tactic:
use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.left⟩
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  apply PushoutCocone.isColimitAux'
  intro s
  use H₂.desc (BinaryCofan.mk s.inl s.inr)
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.left⟩
  

Proof state:
case right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
s : PushoutCocone h k
⊢ PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫
        IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s)) =
      PushoutCocone.inr s ∧
    ∀ {m : (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)).pt ⟶ s.pt},
      PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inl s →
        PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inr s →
          m = IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s))

Next tactic:
use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.right⟩
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  apply PushoutCocone.isColimitAux'
  intro s
  use H₂.desc (BinaryCofan.mk s.inl s.inr)
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.left⟩
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.right⟩
  

Proof state:
case right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
s : PushoutCocone h k
⊢ ∀ {m : (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)).pt ⟶ s.pt},
    PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inl s →
      PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inr s →
        m = IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s))

Next tactic:
intro m h₁ h₂
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  apply PushoutCocone.isColimitAux'
  intro s
  use H₂.desc (BinaryCofan.mk s.inl s.inr)
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.left⟩
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.right⟩
  intro m h₁ h₂
  

Proof state:
case right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
s : PushoutCocone h k
m : (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)).pt ⟶ s.pt
h₁ : PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inl s
h₂ : PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inr s
⊢ m = IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s))

Next tactic:
apply H₂.hom_ext
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  apply PushoutCocone.isColimitAux'
  intro s
  use H₂.desc (BinaryCofan.mk s.inl s.inr)
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.left⟩
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.right⟩
  intro m h₁ h₂
  apply H₂.hom_ext
  

Proof state:
case right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
s : PushoutCocone h k
m : (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)).pt ⟶ s.pt
h₁ : PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inl s
h₂ : PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inr s
⊢ ∀ (j : Discrete WalkingPair),
    (BinaryCofan.mk f g).ι.app j ≫ m =
      (BinaryCofan.mk f g).ι.app j ≫ IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s))

Next tactic:
rintro ⟨⟨⟩⟩
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  apply PushoutCocone.isColimitAux'
  intro s
  use H₂.desc (BinaryCofan.mk s.inl s.inr)
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.left⟩
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.right⟩
  intro m h₁ h₂
  apply H₂.hom_ext
  rintro ⟨⟨⟩⟩
  · 

Proof state:
case right.mk.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
s : PushoutCocone h k
m : (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)).pt ⟶ s.pt
h₁ : PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inl s
h₂ : PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inr s
⊢ (BinaryCofan.mk f g).ι.app { as := WalkingPair.left } ≫ m =
    (BinaryCofan.mk f g).ι.app { as := WalkingPair.left } ≫
      IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s))

Next tactic:
exact h₁.trans (H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.left⟩).symm
/-- The coproduct is the pushout under the initial object. -/
def isPushoutOfIsInitialIsCoproduct {W X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ X) (k : W ⟶ Y)
    (H₁ : IsInitial W) (H₂ : IsColimit (BinaryCofan.mk f g)) :
    IsColimit (PushoutCocone.mk _ _ (show h ≫ f = k ≫ g from H₁.hom_ext _ _)) := by
  apply PushoutCocone.isColimitAux'
  intro s
  use H₂.desc (BinaryCofan.mk s.inl s.inr)
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.left⟩
  use H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.right⟩
  intro m h₁ h₂
  apply H₂.hom_ext
  rintro ⟨⟨⟩⟩
  · exact h₁.trans (H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.left⟩).symm
  · 

Proof state:
case right.mk.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u'
inst✝ : Category.{v', u'} D
F : C ⥤ D
W X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
h : W ⟶ X
k : W ⟶ Y
H₁ : IsInitial W
H₂ : IsColimit (BinaryCofan.mk f g)
s : PushoutCocone h k
m : (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)).pt ⟶ s.pt
h₁ : PushoutCocone.inl (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inl s
h₂ : PushoutCocone.inr (PushoutCocone.mk f g (_ : h ≫ f = k ≫ g)) ≫ m = PushoutCocone.inr s
⊢ (BinaryCofan.mk f g).ι.app { as := WalkingPair.right } ≫ m =
    (BinaryCofan.mk f g).ι.app { as := WalkingPair.right } ≫
      IsColimit.desc H₂ (BinaryCofan.mk (PushoutCocone.inl s) (PushoutCocone.inr s))

Next tactic:
exact h₂.trans (H₂.fac (BinaryCofan.mk s.inl s.inr) ⟨WalkingPair.right⟩).symm