l3lab/ntp-mathlib huggingface dataset:
/-- If `W` is the pullback of `f, g`,
it is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : PullbackCone f g)
    (H : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ f ≫ i = s.snd ≫ g ≫ i by
          rw [← Category.assoc, ← Category.assoc, s.condition])) := by
  apply PullbackCone.isLimitAux'
  

Proof state:
case create
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Z
g✝ : Y ⟶ Z
f : X ⟶ W
g : Y ⟶ W
i : W ⟶ Z
inst✝ : Mono i
s : PullbackCone f g
H : IsLimit s
⊢ (s_1 : PullbackCone (f ≫ i) (g ≫ i)) →
    { l //
      l ≫ fst (mk (fst s) (snd s) (_ : fst s ≫ f ≫ i = snd s ≫ g ≫ i)) = fst s_1 ∧
        l ≫ snd (mk (fst s) (snd s) (_ : fst s ≫ f ≫ i = snd s ≫ g ≫ i)) = snd s_1 ∧
          ∀ {m : s_1.pt ⟶ (mk (fst s) (snd s) (_ : fst s ≫ f ≫ i = snd s ≫ g ≫ i)).pt},
            m ≫ fst (mk (fst s) (snd s) (_ : fst s ≫ f ≫ i = snd s ≫ g ≫ i)) = fst s_1 →
              m ≫ snd (mk (fst s) (snd s) (_ : fst s ≫ f ≫ i = snd s ≫ g ≫ i)) = snd s_1 → m = l }

Next tactic:
intro s
/-- If `W` is the pullback of `f, g`,
it is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : PullbackCone f g)
    (H : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ f ≫ i = s.snd ≫ g ≫ i by
          rw [← Category.assoc, ← Category.assoc, s.condition])) := by
  apply PullbackCone.isLimitAux'
  intro s
  

Proof state:
case create
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Z
g✝ : Y ⟶ Z
f : X ⟶ W
g : Y ⟶ W
i : W ⟶ Z
inst✝ : Mono i
s✝ : PullbackCone f g
H : IsLimit s✝
s : PullbackCone (f ≫ i) (g ≫ i)
⊢ { l //
    l ≫ fst (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = fst s ∧
      l ≫ snd (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = snd s ∧
        ∀ {m : s.pt ⟶ (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)).pt},
          m ≫ fst (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = fst s →
            m ≫ snd (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = snd s → m = l }

Next tactic:
rcases PullbackCone.IsLimit.lift' H s.fst s.snd
      ((cancel_mono i).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
/-- If `W` is the pullback of `f, g`,
it is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : PullbackCone f g)
    (H : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ f ≫ i = s.snd ≫ g ≫ i by
          rw [← Category.assoc, ← Category.assoc, s.condition])) := by
  apply PullbackCone.isLimitAux'
  intro s
  rcases PullbackCone.IsLimit.lift' H s.fst s.snd
      ((cancel_mono i).mp (by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Z
g✝ : Y ⟶ Z
f : X ⟶ W
g : Y ⟶ W
i : W ⟶ Z
inst✝ : Mono i
s✝ : PullbackCone f g
H : IsLimit s✝
s : PullbackCone (f ≫ i) (g ≫ i)
⊢ (fst s ≫ f) ≫ i = (snd s ≫ g) ≫ i

Next tactic:
simpa using s.condition
/-- If `W` is the pullback of `f, g`,
it is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : PullbackCone f g)
    (H : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ f ≫ i = s.snd ≫ g ≫ i by
          rw [← Category.assoc, ← Category.assoc, s.condition])) := by
  apply PullbackCone.isLimitAux'
  intro s
  rcases PullbackCone.IsLimit.lift' H s.fst s.snd
      ((cancel_mono i).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
  

Proof state:
case create.mk.intro
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Z
g✝ : Y ⟶ Z
f : X ⟶ W
g : Y ⟶ W
i : W ⟶ Z
inst✝ : Mono i
s✝ : PullbackCone f g
H : IsLimit s✝
s : PullbackCone (f ≫ i) (g ≫ i)
l : s.pt ⟶ s✝.pt
h₁ : l ≫ fst s✝ = fst s
h₂ : l ≫ snd s✝ = snd s
⊢ { l //
    l ≫ fst (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = fst s ∧
      l ≫ snd (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = snd s ∧
        ∀ {m : s.pt ⟶ (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)).pt},
          m ≫ fst (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = fst s →
            m ≫ snd (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = snd s → m = l }

Next tactic:
refine' ⟨l, h₁, h₂, _⟩
/-- If `W` is the pullback of `f, g`,
it is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : PullbackCone f g)
    (H : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ f ≫ i = s.snd ≫ g ≫ i by
          rw [← Category.assoc, ← Category.assoc, s.condition])) := by
  apply PullbackCone.isLimitAux'
  intro s
  rcases PullbackCone.IsLimit.lift' H s.fst s.snd
      ((cancel_mono i).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
  refine' ⟨l, h₁, h₂, _⟩
  

Proof state:
case create.mk.intro
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Z
g✝ : Y ⟶ Z
f : X ⟶ W
g : Y ⟶ W
i : W ⟶ Z
inst✝ : Mono i
s✝ : PullbackCone f g
H : IsLimit s✝
s : PullbackCone (f ≫ i) (g ≫ i)
l : s.pt ⟶ s✝.pt
h₁ : l ≫ fst s✝ = fst s
h₂ : l ≫ snd s✝ = snd s
⊢ ∀ {m : s.pt ⟶ (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)).pt},
    m ≫ fst (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = fst s →
      m ≫ snd (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = snd s → m = l

Next tactic:
intro m hm₁ hm₂
/-- If `W` is the pullback of `f, g`,
it is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : PullbackCone f g)
    (H : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ f ≫ i = s.snd ≫ g ≫ i by
          rw [← Category.assoc, ← Category.assoc, s.condition])) := by
  apply PullbackCone.isLimitAux'
  intro s
  rcases PullbackCone.IsLimit.lift' H s.fst s.snd
      ((cancel_mono i).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
  refine' ⟨l, h₁, h₂, _⟩
  intro m hm₁ hm₂
  

Proof state:
case create.mk.intro
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Z
g✝ : Y ⟶ Z
f : X ⟶ W
g : Y ⟶ W
i : W ⟶ Z
inst✝ : Mono i
s✝ : PullbackCone f g
H : IsLimit s✝
s : PullbackCone (f ≫ i) (g ≫ i)
l : s.pt ⟶ s✝.pt
h₁ : l ≫ fst s✝ = fst s
h₂ : l ≫ snd s✝ = snd s
m : s.pt ⟶ (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)).pt
hm₁ : m ≫ fst (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = fst s
hm₂ : m ≫ snd (mk (fst s✝) (snd s✝) (_ : fst s✝ ≫ f ≫ i = snd s✝ ≫ g ≫ i)) = snd s
⊢ m = l

Next tactic:
exact (PullbackCone.IsLimit.hom_ext H (hm₁.trans h₁.symm) (hm₂.trans h₂.symm) : _)
@[simp]
theorem condition_zero (t : PushoutCocone f g) : t.ι.app WalkingSpan.zero = f ≫ t.inl := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
t : PushoutCocone f g
⊢ t.ι.app WalkingSpan.zero = f ≫ inl t

Next tactic:
have w := t.ι.naturality WalkingSpan.Hom.fst
@[simp]
theorem condition_zero (t : PushoutCocone f g) : t.ι.app WalkingSpan.zero = f ≫ t.inl := by
  have w := t.ι.naturality WalkingSpan.Hom.fst
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
t : PushoutCocone f g
w :
  (span f g).map fst ≫ t.ι.app WalkingSpan.left =
    t.ι.app WalkingSpan.zero ≫ ((Functor.const WalkingSpan).obj t.pt).map fst
⊢ t.ι.app WalkingSpan.zero = f ≫ inl t

Next tactic:
dsimp at w
@[simp]
theorem condition_zero (t : PushoutCocone f g) : t.ι.app WalkingSpan.zero = f ≫ t.inl := by
  have w := t.ι.naturality WalkingSpan.Hom.fst
  dsimp at w; 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
t : PushoutCocone f g
w : f ≫ inl t = t.ι.app WalkingSpan.zero ≫ 𝟙 t.pt
⊢ t.ι.app WalkingSpan.zero = f ≫ inl t

Next tactic:
simpa using w.symm
/-- This is a slightly more convenient method to verify that a pushout cocone is a colimit cocone.
    It only asks for a proof of facts that carry any mathematical content -/
def isColimitAux (t : PushoutCocone f g) (desc : ∀ s : PushoutCocone f g, t.pt ⟶ s.pt)
    (fac_left : ∀ s : PushoutCocone f g, t.inl ≫ desc s = s.inl)
    (fac_right : ∀ s : PushoutCocone f g, t.inr ≫ desc s = s.inr)
    (uniq : ∀ (s : PushoutCocone f g) (m : t.pt ⟶ s.pt)
    (_ : ∀ j : WalkingSpan, t.ι.app j ≫ m = s.ι.app j), m = desc s) : IsColimit t :=
  { desc
    fac := fun s j =>
      Option.casesOn j (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
t : PushoutCocone f g
desc : (s : PushoutCocone f g) → t.pt ⟶ s.pt
fac_left : ∀ (s : PushoutCocone f g), inl t ≫ desc s = inl s
fac_right : ∀ (s : PushoutCocone f g), inr t ≫ desc s = inr s
uniq : ∀ (s : PushoutCocone f g) (m : t.pt ⟶ s.pt), (∀ (j : WalkingSpan), t.ι.app j ≫ m = s.ι.app j) → m = desc s
s : Cocone (span f g)
j : WalkingSpan
⊢ t.ι.app none ≫ desc s = s.ι.app none

Next tactic:
simp [← s.w fst, ← t.w fst, fac_left s]
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ ⦃X_1 Y_1 : WalkingSpan⦄ (f_1 : X_1 ⟶ Y_1),
    (span f g).map f_1 ≫ (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) Y_1 =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) X_1 ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩)
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> 

Proof state:
case none.none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ (f_1 : none ⟶ none),
    (span f g).map f_1 ≫ (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
intro f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> 

Proof state:
case none.some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ (f_1 : none ⟶ some WalkingPair.left),
    (span f g).map f_1 ≫
        (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
intro f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> 

Proof state:
case none.some.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ (f_1 : none ⟶ some WalkingPair.right),
    (span f g).map f_1 ≫
        (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.right) =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
intro f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> 

Proof state:
case some.left.none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ (f_1 : some WalkingPair.left ⟶ none),
    (span f g).map f_1 ≫ (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
intro f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> 

Proof state:
case some.left.some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ (f_1 : some WalkingPair.left ⟶ some WalkingPair.left),
    (span f g).map f_1 ≫
        (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
intro f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> 

Proof state:
case some.left.some.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ (f_1 : some WalkingPair.left ⟶ some WalkingPair.right),
    (span f g).map f_1 ≫
        (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.right) =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
intro f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> 

Proof state:
case some.right.none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ (f_1 : some WalkingPair.right ⟶ none),
    (span f g).map f_1 ≫ (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.right) ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
intro f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> 

Proof state:
case some.right.some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ (f_1 : some WalkingPair.right ⟶ some WalkingPair.left),
    (span f g).map f_1 ≫
        (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.right) ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
intro f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> 

Proof state:
case some.right.some.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f ≫ inl = g ≫ inr
⊢ ∀ (f_1 : some WalkingPair.right ⟶ some WalkingPair.right),
    (span f g).map f_1 ≫
        (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.right) =
      (fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.right) ≫
        ((Functor.const WalkingSpan).obj W).map f_1

Next tactic:
intro f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> intro f <;> 

Proof state:
case none.none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f✝ : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f✝ ≫ inl = g ≫ inr
f : none ⟶ none
⊢ (span f✝ g).map f ≫ (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none =
    (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none ≫
      ((Functor.const WalkingSpan).obj W).map f

Next tactic:
cases f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> intro f <;> 

Proof state:
case none.some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f✝ : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f✝ ≫ inl = g ≫ inr
f : none ⟶ some WalkingPair.left
⊢ (span f✝ g).map f ≫
      (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) =
    (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none ≫
      ((Functor.const WalkingSpan).obj W).map f

Next tactic:
cases f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> intro f <;> 

Proof state:
case none.some.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f✝ : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f✝ ≫ inl = g ≫ inr
f : none ⟶ some WalkingPair.right
⊢ (span f✝ g).map f ≫
      (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.right) =
    (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none ≫
      ((Functor.const WalkingSpan).obj W).map f

Next tactic:
cases f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> intro f <;> 

Proof state:
case some.left.none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f✝ : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f✝ ≫ inl = g ≫ inr
f : some WalkingPair.left ⟶ none
⊢ (span f✝ g).map f ≫ (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) none =
    (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) ≫
      ((Functor.const WalkingSpan).obj W).map f

Next tactic:
cases f
/-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g where
  pt := W
  ι := { app := fun j => Option.casesOn j (f ≫ inl) fun j' => WalkingPair.casesOn j' inl inr
         naturality := by
          rintro (⟨⟩|⟨⟨⟩⟩) (⟨⟩|⟨⟨⟩⟩) <;> intro f <;> 

Proof state:
case some.left.some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W✝ X Y Z : C
f✝ : X ⟶ Y
g : X ⟶ Z
W : C
inl : Y ⟶ W
inr : Z ⟶ W
eq : f✝ ≫ inl = g ≫ inr
f : some WalkingPair.left ⟶ some WalkingPair.left
⊢ (span f✝ g).map f ≫
      (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) =
    (fun j => Option.casesOn j (f✝ ≫ inl) fun j' => WalkingPair.casesOn j' inl inr) (some WalkingPair.left) ≫
      ((Functor.const WalkingSpan).obj W).map f

Next tactic:
cases f