l3lab/ntp-mathlib huggingface dataset:
/-- If a functor preserves equalizers and the appropriate products, it preserves limits. -/
noncomputable def preservesLimitOfPreservesEqualizersAndProduct : PreservesLimitsOfShape J G where
  preservesLimit {K} := by
    let P := ∏ K.obj
    let Q := ∏ fun f : Σp : J × J, p.fst ⟶ p.snd => K.obj f.1.2
    let s : P ⟶ Q := Pi.lift fun f => limit.π (Discrete.functor K.obj) ⟨_⟩ ≫ K.map f.2
    let t : P ⟶ Q := Pi.lift fun f => limit.π (Discrete.functor K.obj) ⟨f.1.2⟩
    let I := equalizer s t
    let i : I ⟶ P := equalizer.ι s t
    apply
      preservesLimitOfPreservesLimitCone
        (buildIsLimit s t (by simp) (by simp) (limit.isLimit _) (limit.isLimit _)
          (limit.isLimit _))
    refine' IsLimit.ofIsoLimit (buildIsLimit _ _ _ _ _ _ _) _
    · exact Fan.mk _ fun j => G.map (Pi.π _ j)
    · exact Fan.mk (G.obj Q) fun f => G.map (Pi.π _ f)
    · apply G.map s
    · apply G.map t
    · intro f
      dsimp [Fan.mk]
      simp only [← G.map_comp, limit.lift_π]
      congr
    · intro f
      dsimp [Fan.mk]
      simp only [← G.map_comp, limit.lift_π]
      apply congrArg G.map
      dsimp
    · apply Fork.ofι (G.map i)
      rw [← G.map_comp, ← G.map_comp]
      apply congrArg G.map
      exact equalizer.condition s t
    · apply isLimitOfHasProductOfPreservesLimit
    · apply isLimitOfHasProductOfPreservesLimit
    · apply isLimitForkMapOfIsLimit
      apply equalizerIsEqualizer
    · refine Cones.ext (Iso.refl _) ?_
      intro j; dsimp; 

Proof state:
case refine'_11
C : Type u
inst✝⁸ : Category.{v, u} C
J : Type w
inst✝⁷ : SmallCategory J
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
inst✝⁵ : HasLimitsOfShape (Discrete J) C
inst✝⁴ : HasLimitsOfShape (Discrete ((p : J × J) × (p.1 ⟶ p.2))) C
inst✝³ : HasEqualizers C
G : C ⥤ D
inst✝² : PreservesLimitsOfShape WalkingParallelPair G
inst✝¹ : PreservesLimitsOfShape (Discrete J) G
inst✝ : PreservesLimitsOfShape (Discrete ((p : J × J) × (p.1 ⟶ p.2))) G
K : J ⥤ C
P : C := ∏ K.obj
Q : C := ∏ fun f => K.obj f.fst.2
s : P ⟶ Q := Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.1 } ≫ K.map f.snd
t : P ⟶ Q := Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.2 }
I : C := equalizer s t
i : I ⟶ P := equalizer.ι s t
j : J
⊢ G.map
        (equalizer.ι (Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.1 } ≫ K.map f.snd)
          (Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.2 })) ≫
      G.map (Pi.π (fun j => K.obj j) j) =
    𝟙
        (G.obj
          (equalizer (Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.1 } ≫ K.map f.snd)
            (Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.2 }))) ≫
      G.map
        (equalizer.ι (Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.1 } ≫ K.map f.snd)
            (Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.2 }) ≫
          limit.π (Discrete.functor K.obj) { as := j })

Next tactic:
simp
/-- If G preserves equalizers and finite products, it preserves finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts [HasEqualizers C]
    [HasFiniteProducts C] (G : C ⥤ D) [PreservesLimitsOfShape WalkingParallelPair G]
    [PreservesFiniteProducts G] : PreservesFiniteLimits G where
  preservesFiniteLimits := by
    

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : Type w
inst✝⁵ : SmallCategory J
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasEqualizers C
inst✝² : HasFiniteProducts C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape WalkingParallelPair G
inst✝ : PreservesFiniteProducts G
⊢ (J : Type) → [inst : SmallCategory J] → [inst_1 : FinCategory J] → PreservesLimitsOfShape J G

Next tactic:
intro J sJ fJ
/-- If G preserves equalizers and finite products, it preserves finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts [HasEqualizers C]
    [HasFiniteProducts C] (G : C ⥤ D) [PreservesLimitsOfShape WalkingParallelPair G]
    [PreservesFiniteProducts G] : PreservesFiniteLimits G where
  preservesFiniteLimits := by
    intro J sJ fJ
    

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J✝ : Type w
inst✝⁵ : SmallCategory J✝
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasEqualizers C
inst✝² : HasFiniteProducts C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape WalkingParallelPair G
inst✝ : PreservesFiniteProducts G
J : Type
sJ : SmallCategory J
fJ : FinCategory J
⊢ PreservesLimitsOfShape J G

Next tactic:
haveI : Fintype J := inferInstance
/-- If G preserves equalizers and finite products, it preserves finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts [HasEqualizers C]
    [HasFiniteProducts C] (G : C ⥤ D) [PreservesLimitsOfShape WalkingParallelPair G]
    [PreservesFiniteProducts G] : PreservesFiniteLimits G where
  preservesFiniteLimits := by
    intro J sJ fJ
    haveI : Fintype J := inferInstance
    

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J✝ : Type w
inst✝⁵ : SmallCategory J✝
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasEqualizers C
inst✝² : HasFiniteProducts C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape WalkingParallelPair G
inst✝ : PreservesFiniteProducts G
J : Type
sJ : SmallCategory J
fJ : FinCategory J
this : Fintype J
⊢ PreservesLimitsOfShape J G

Next tactic:
haveI : Fintype ((p : J × J) × (p.fst ⟶ p.snd)) := inferInstance
/-- If G preserves equalizers and finite products, it preserves finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts [HasEqualizers C]
    [HasFiniteProducts C] (G : C ⥤ D) [PreservesLimitsOfShape WalkingParallelPair G]
    [PreservesFiniteProducts G] : PreservesFiniteLimits G where
  preservesFiniteLimits := by
    intro J sJ fJ
    haveI : Fintype J := inferInstance
    haveI : Fintype ((p : J × J) × (p.fst ⟶ p.snd)) := inferInstance
    

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J✝ : Type w
inst✝⁵ : SmallCategory J✝
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasEqualizers C
inst✝² : HasFiniteProducts C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape WalkingParallelPair G
inst✝ : PreservesFiniteProducts G
J : Type
sJ : SmallCategory J
fJ : FinCategory J
this✝ : Fintype J
this : Fintype ((p : J × J) × (p.1 ⟶ p.2))
⊢ PreservesLimitsOfShape J G

Next tactic:
apply @preservesLimitOfPreservesEqualizersAndProduct _ _ _ sJ _ _ ?_ ?_ _ G _ ?_ ?_
/-- If G preserves equalizers and finite products, it preserves finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts [HasEqualizers C]
    [HasFiniteProducts C] (G : C ⥤ D) [PreservesLimitsOfShape WalkingParallelPair G]
    [PreservesFiniteProducts G] : PreservesFiniteLimits G where
  preservesFiniteLimits := by
    intro J sJ fJ
    haveI : Fintype J := inferInstance
    haveI : Fintype ((p : J × J) × (p.fst ⟶ p.snd)) := inferInstance
    apply @preservesLimitOfPreservesEqualizersAndProduct _ _ _ sJ _ _ ?_ ?_ _ G _ ?_ ?_
    · 

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J✝ : Type w
inst✝⁵ : SmallCategory J✝
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasEqualizers C
inst✝² : HasFiniteProducts C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape WalkingParallelPair G
inst✝ : PreservesFiniteProducts G
J : Type
sJ : SmallCategory J
fJ : FinCategory J
this✝ : Fintype J
this : Fintype ((p : J × J) × (p.1 ⟶ p.2))
⊢ HasLimitsOfShape (Discrete J) C

Next tactic:
apply hasLimitsOfShape_discrete _ _
/-- If G preserves equalizers and finite products, it preserves finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts [HasEqualizers C]
    [HasFiniteProducts C] (G : C ⥤ D) [PreservesLimitsOfShape WalkingParallelPair G]
    [PreservesFiniteProducts G] : PreservesFiniteLimits G where
  preservesFiniteLimits := by
    intro J sJ fJ
    haveI : Fintype J := inferInstance
    haveI : Fintype ((p : J × J) × (p.fst ⟶ p.snd)) := inferInstance
    apply @preservesLimitOfPreservesEqualizersAndProduct _ _ _ sJ _ _ ?_ ?_ _ G _ ?_ ?_
    · apply hasLimitsOfShape_discrete _ _
    · 

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J✝ : Type w
inst✝⁵ : SmallCategory J✝
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasEqualizers C
inst✝² : HasFiniteProducts C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape WalkingParallelPair G
inst✝ : PreservesFiniteProducts G
J : Type
sJ : SmallCategory J
fJ : FinCategory J
this✝ : Fintype J
this : Fintype ((p : J × J) × (p.1 ⟶ p.2))
⊢ HasLimitsOfShape (Discrete ((p : J × J) × (p.1 ⟶ p.2))) C

Next tactic:
apply hasLimitsOfShape_discrete _
/-- If G preserves equalizers and finite products, it preserves finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts [HasEqualizers C]
    [HasFiniteProducts C] (G : C ⥤ D) [PreservesLimitsOfShape WalkingParallelPair G]
    [PreservesFiniteProducts G] : PreservesFiniteLimits G where
  preservesFiniteLimits := by
    intro J sJ fJ
    haveI : Fintype J := inferInstance
    haveI : Fintype ((p : J × J) × (p.fst ⟶ p.snd)) := inferInstance
    apply @preservesLimitOfPreservesEqualizersAndProduct _ _ _ sJ _ _ ?_ ?_ _ G _ ?_ ?_
    · apply hasLimitsOfShape_discrete _ _
    · apply hasLimitsOfShape_discrete _
    · 

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J✝ : Type w
inst✝⁵ : SmallCategory J✝
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasEqualizers C
inst✝² : HasFiniteProducts C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape WalkingParallelPair G
inst✝ : PreservesFiniteProducts G
J : Type
sJ : SmallCategory J
fJ : FinCategory J
this✝ : Fintype J
this : Fintype ((p : J × J) × (p.1 ⟶ p.2))
⊢ PreservesLimitsOfShape (Discrete J) G

Next tactic:
apply PreservesFiniteProducts.preserves _
/-- If G preserves equalizers and finite products, it preserves finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts [HasEqualizers C]
    [HasFiniteProducts C] (G : C ⥤ D) [PreservesLimitsOfShape WalkingParallelPair G]
    [PreservesFiniteProducts G] : PreservesFiniteLimits G where
  preservesFiniteLimits := by
    intro J sJ fJ
    haveI : Fintype J := inferInstance
    haveI : Fintype ((p : J × J) × (p.fst ⟶ p.snd)) := inferInstance
    apply @preservesLimitOfPreservesEqualizersAndProduct _ _ _ sJ _ _ ?_ ?_ _ G _ ?_ ?_
    · apply hasLimitsOfShape_discrete _ _
    · apply hasLimitsOfShape_discrete _
    · apply PreservesFiniteProducts.preserves _
    · 

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J✝ : Type w
inst✝⁵ : SmallCategory J✝
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasEqualizers C
inst✝² : HasFiniteProducts C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape WalkingParallelPair G
inst✝ : PreservesFiniteProducts G
J : Type
sJ : SmallCategory J
fJ : FinCategory J
this✝ : Fintype J
this : Fintype ((p : J × J) × (p.1 ⟶ p.2))
⊢ PreservesLimitsOfShape (Discrete ((p : J × J) × (p.1 ⟶ p.2))) G

Next tactic:
apply PreservesFiniteProducts.preserves _
/-- If G preserves terminal objects and pullbacks, it preserves all finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesTerminalAndPullbacks [HasTerminal C]
    [HasPullbacks C] (G : C ⥤ D) [PreservesLimitsOfShape (Discrete.{0} PEmpty) G]
    [PreservesLimitsOfShape WalkingCospan G] : PreservesFiniteLimits G := by
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : Type w
inst✝⁵ : SmallCategory J
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasTerminal C
inst✝² : HasPullbacks C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape (Discrete PEmpty.{1}) G
inst✝ : PreservesLimitsOfShape WalkingCospan G
⊢ PreservesFiniteLimits G

Next tactic:
haveI : HasFiniteLimits C := hasFiniteLimits_of_hasTerminal_and_pullbacks
/-- If G preserves terminal objects and pullbacks, it preserves all finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesTerminalAndPullbacks [HasTerminal C]
    [HasPullbacks C] (G : C ⥤ D) [PreservesLimitsOfShape (Discrete.{0} PEmpty) G]
    [PreservesLimitsOfShape WalkingCospan G] : PreservesFiniteLimits G := by
  haveI : HasFiniteLimits C := hasFiniteLimits_of_hasTerminal_and_pullbacks
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : Type w
inst✝⁵ : SmallCategory J
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasTerminal C
inst✝² : HasPullbacks C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape (Discrete PEmpty.{1}) G
inst✝ : PreservesLimitsOfShape WalkingCospan G
this : HasFiniteLimits C
⊢ PreservesFiniteLimits G

Next tactic:
haveI : PreservesLimitsOfShape (Discrete WalkingPair) G :=
    preservesBinaryProductsOfPreservesTerminalAndPullbacks G
/-- If G preserves terminal objects and pullbacks, it preserves all finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesTerminalAndPullbacks [HasTerminal C]
    [HasPullbacks C] (G : C ⥤ D) [PreservesLimitsOfShape (Discrete.{0} PEmpty) G]
    [PreservesLimitsOfShape WalkingCospan G] : PreservesFiniteLimits G := by
  haveI : HasFiniteLimits C := hasFiniteLimits_of_hasTerminal_and_pullbacks
  haveI : PreservesLimitsOfShape (Discrete WalkingPair) G :=
    preservesBinaryProductsOfPreservesTerminalAndPullbacks G
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : Type w
inst✝⁵ : SmallCategory J
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasTerminal C
inst✝² : HasPullbacks C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape (Discrete PEmpty.{1}) G
inst✝ : PreservesLimitsOfShape WalkingCospan G
this✝ : HasFiniteLimits C
this : PreservesLimitsOfShape (Discrete WalkingPair) G
⊢ PreservesFiniteLimits G

Next tactic:
haveI : PreservesLimitsOfShape WalkingParallelPair G :=
      preservesEqualizersOfPreservesPullbacksAndBinaryProducts G
/-- If G preserves terminal objects and pullbacks, it preserves all finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesTerminalAndPullbacks [HasTerminal C]
    [HasPullbacks C] (G : C ⥤ D) [PreservesLimitsOfShape (Discrete.{0} PEmpty) G]
    [PreservesLimitsOfShape WalkingCospan G] : PreservesFiniteLimits G := by
  haveI : HasFiniteLimits C := hasFiniteLimits_of_hasTerminal_and_pullbacks
  haveI : PreservesLimitsOfShape (Discrete WalkingPair) G :=
    preservesBinaryProductsOfPreservesTerminalAndPullbacks G
  haveI : PreservesLimitsOfShape WalkingParallelPair G :=
      preservesEqualizersOfPreservesPullbacksAndBinaryProducts G
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : Type w
inst✝⁵ : SmallCategory J
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasTerminal C
inst✝² : HasPullbacks C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape (Discrete PEmpty.{1}) G
inst✝ : PreservesLimitsOfShape WalkingCospan G
this✝¹ : HasFiniteLimits C
this✝ : PreservesLimitsOfShape (Discrete WalkingPair) G
this : PreservesLimitsOfShape WalkingParallelPair G
⊢ PreservesFiniteLimits G

Next tactic:
apply
    @preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts _ _ _ _ _ _ G _ ?_
/-- If G preserves terminal objects and pullbacks, it preserves all finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesTerminalAndPullbacks [HasTerminal C]
    [HasPullbacks C] (G : C ⥤ D) [PreservesLimitsOfShape (Discrete.{0} PEmpty) G]
    [PreservesLimitsOfShape WalkingCospan G] : PreservesFiniteLimits G := by
  haveI : HasFiniteLimits C := hasFiniteLimits_of_hasTerminal_and_pullbacks
  haveI : PreservesLimitsOfShape (Discrete WalkingPair) G :=
    preservesBinaryProductsOfPreservesTerminalAndPullbacks G
  haveI : PreservesLimitsOfShape WalkingParallelPair G :=
      preservesEqualizersOfPreservesPullbacksAndBinaryProducts G
  apply
    @preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts _ _ _ _ _ _ G _ ?_
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : Type w
inst✝⁵ : SmallCategory J
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasTerminal C
inst✝² : HasPullbacks C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape (Discrete PEmpty.{1}) G
inst✝ : PreservesLimitsOfShape WalkingCospan G
this✝¹ : HasFiniteLimits C
this✝ : PreservesLimitsOfShape (Discrete WalkingPair) G
this : PreservesLimitsOfShape WalkingParallelPair G
⊢ PreservesFiniteProducts G

Next tactic:
apply PreservesFiniteProducts.mk
/-- If G preserves terminal objects and pullbacks, it preserves all finite limits. -/
noncomputable def preservesFiniteLimitsOfPreservesTerminalAndPullbacks [HasTerminal C]
    [HasPullbacks C] (G : C ⥤ D) [PreservesLimitsOfShape (Discrete.{0} PEmpty) G]
    [PreservesLimitsOfShape WalkingCospan G] : PreservesFiniteLimits G := by
  haveI : HasFiniteLimits C := hasFiniteLimits_of_hasTerminal_and_pullbacks
  haveI : PreservesLimitsOfShape (Discrete WalkingPair) G :=
    preservesBinaryProductsOfPreservesTerminalAndPullbacks G
  haveI : PreservesLimitsOfShape WalkingParallelPair G :=
      preservesEqualizersOfPreservesPullbacksAndBinaryProducts G
  apply
    @preservesFiniteLimitsOfPreservesEqualizersAndFiniteProducts _ _ _ _ _ _ G _ ?_
  apply PreservesFiniteProducts.mk
  

Proof state:
case preserves
C : Type u
inst✝⁶ : Category.{v, u} C
J : Type w
inst✝⁵ : SmallCategory J
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
inst✝³ : HasTerminal C
inst✝² : HasPullbacks C
G : C ⥤ D
inst✝¹ : PreservesLimitsOfShape (Discrete PEmpty.{1}) G
inst✝ : PreservesLimitsOfShape WalkingCospan G
this✝¹ : HasFiniteLimits C
this✝ : PreservesLimitsOfShape (Discrete WalkingPair) G
this : PreservesLimitsOfShape WalkingParallelPair G
⊢ (J : Type) → [inst : Fintype J] → PreservesLimitsOfShape (Discrete J) G

Next tactic:
apply preservesFiniteProductsOfPreservesBinaryAndTerminal G
/-- (Implementation) Given the appropriate coproduct and coequalizer cocones,
build the cocone for `F` which is colimiting if the given cocones are also.
-/
@[simps]
def buildColimit : Cocone F where
  pt := i.pt
  ι :=
    { app := fun j => c₂.ι.app ⟨_⟩ ≫ i.π
      naturality := fun j₁ j₂ f => by
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
J : Type w
inst✝¹ : SmallCategory J
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : J ⥤ C
c₁ : Cofan fun f => F.obj f.fst.1
c₂ : Cofan F.obj
s t : c₁.pt ⟶ c₂.pt
hs : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ s = F.map f.snd ≫ c₂.ι.app { as := f.fst.2 }
ht : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ t = c₂.ι.app { as := f.fst.1 }
i : Cofork s t
j₁ j₂ : J
f : j₁ ⟶ j₂
⊢ F.map f ≫ (fun j => c₂.ι.app { as := j } ≫ Cofork.π i) j₂ =
    (fun j => c₂.ι.app { as := j } ≫ Cofork.π i) j₁ ≫ ((Functor.const J).obj i.pt).map f

Next tactic:
dsimp
/-- (Implementation) Given the appropriate coproduct and coequalizer cocones,
build the cocone for `F` which is colimiting if the given cocones are also.
-/
@[simps]
def buildColimit : Cocone F where
  pt := i.pt
  ι :=
    { app := fun j => c₂.ι.app ⟨_⟩ ≫ i.π
      naturality := fun j₁ j₂ f => by
        dsimp
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
J : Type w
inst✝¹ : SmallCategory J
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : J ⥤ C
c₁ : Cofan fun f => F.obj f.fst.1
c₂ : Cofan F.obj
s t : c₁.pt ⟶ c₂.pt
hs : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ s = F.map f.snd ≫ c₂.ι.app { as := f.fst.2 }
ht : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ t = c₂.ι.app { as := f.fst.1 }
i : Cofork s t
j₁ j₂ : J
f : j₁ ⟶ j₂
⊢ F.map f ≫ c₂.ι.app { as := j₂ } ≫ Cofork.π i = (c₂.ι.app { as := j₁ } ≫ Cofork.π i) ≫ 𝟙 i.pt

Next tactic:
have reassoced (f : (p : J × J) × (p.fst ⟶ p.snd)) {W : C} {h : _ ⟶ W} :
          c₁.ι.app ⟨f⟩ ≫ s ≫ h = F.map f.snd ≫ c₂.ι.app ⟨f.fst.snd⟩ ≫ h := by
            simp only [← Category.assoc, eq_whisker (hs f)]
/-- (Implementation) Given the appropriate coproduct and coequalizer cocones,
build the cocone for `F` which is colimiting if the given cocones are also.
-/
@[simps]
def buildColimit : Cocone F where
  pt := i.pt
  ι :=
    { app := fun j => c₂.ι.app ⟨_⟩ ≫ i.π
      naturality := fun j₁ j₂ f => by
        dsimp
        have reassoced (f : (p : J × J) × (p.fst ⟶ p.snd)) {W : C} {h : _ ⟶ W} :
          c₁.ι.app ⟨f⟩ ≫ s ≫ h = F.map f.snd ≫ c₂.ι.app ⟨f.fst.snd⟩ ≫ h := by
            

Proof state:
C : Type u
inst✝² : Category.{v, u} C
J : Type w
inst✝¹ : SmallCategory J
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : J ⥤ C
c₁ : Cofan fun f => F.obj f.fst.1
c₂ : Cofan F.obj
s t : c₁.pt ⟶ c₂.pt
hs : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ s = F.map f.snd ≫ c₂.ι.app { as := f.fst.2 }
ht : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ t = c₂.ι.app { as := f.fst.1 }
i : Cofork s t
j₁ j₂ : J
f✝ : j₁ ⟶ j₂
f : (p : J × J) × (p.1 ⟶ p.2)
W : C
h : c₂.pt ⟶ W
⊢ c₁.ι.app { as := f } ≫ s ≫ h = F.map f.snd ≫ c₂.ι.app { as := f.fst.2 } ≫ h

Next tactic:
simp only [← Category.assoc, eq_whisker (hs f)]
/-- (Implementation) Given the appropriate coproduct and coequalizer cocones,
build the cocone for `F` which is colimiting if the given cocones are also.
-/
@[simps]
def buildColimit : Cocone F where
  pt := i.pt
  ι :=
    { app := fun j => c₂.ι.app ⟨_⟩ ≫ i.π
      naturality := fun j₁ j₂ f => by
        dsimp
        have reassoced (f : (p : J × J) × (p.fst ⟶ p.snd)) {W : C} {h : _ ⟶ W} :
          c₁.ι.app ⟨f⟩ ≫ s ≫ h = F.map f.snd ≫ c₂.ι.app ⟨f.fst.snd⟩ ≫ h := by
            simp only [← Category.assoc, eq_whisker (hs f)]
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
J : Type w
inst✝¹ : SmallCategory J
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : J ⥤ C
c₁ : Cofan fun f => F.obj f.fst.1
c₂ : Cofan F.obj
s t : c₁.pt ⟶ c₂.pt
hs : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ s = F.map f.snd ≫ c₂.ι.app { as := f.fst.2 }
ht : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ t = c₂.ι.app { as := f.fst.1 }
i : Cofork s t
j₁ j₂ : J
f : j₁ ⟶ j₂
reassoced :
  ∀ (f : (p : J × J) × (p.1 ⟶ p.2)) {W : C} {h : c₂.pt ⟶ W},
    c₁.ι.app { as := f } ≫ s ≫ h = F.map f.snd ≫ c₂.ι.app { as := f.fst.2 } ≫ h
⊢ F.map f ≫ c₂.ι.app { as := j₂ } ≫ Cofork.π i = (c₂.ι.app { as := j₁ } ≫ Cofork.π i) ≫ 𝟙 i.pt

Next tactic:
rw [Category.comp_id, ← reassoced ⟨⟨_, _⟩, f⟩, i.condition, ← Category.assoc, ht]
/-- (Implementation) Show the cocone constructed in `buildColimit` is colimiting,
provided the cocones used in its construction are.
-/
def buildIsColimit (t₁ : IsColimit c₁) (t₂ : IsColimit c₂) (hi : IsColimit i) :
    IsColimit (buildColimit s t hs ht i) where
  desc q := by
    

Proof state:
C : Type u
inst✝² : Category.{v, u} C
J : Type w
inst✝¹ : SmallCategory J
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : J ⥤ C
c₁ : Cofan fun f => F.obj f.fst.1
c₂ : Cofan F.obj
s t : c₁.pt ⟶ c₂.pt
hs : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ s = F.map f.snd ≫ c₂.ι.app { as := f.fst.2 }
ht : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ t = c₂.ι.app { as := f.fst.1 }
i : Cofork s t
t₁ : IsColimit c₁
t₂ : IsColimit c₂
hi : IsColimit i
q : Cocone F
⊢ (buildColimit s t hs ht i).pt ⟶ q.pt

Next tactic:
refine' hi.desc (Cofork.ofπ _ _)
/-- (Implementation) Show the cocone constructed in `buildColimit` is colimiting,
provided the cocones used in its construction are.
-/
def buildIsColimit (t₁ : IsColimit c₁) (t₂ : IsColimit c₂) (hi : IsColimit i) :
    IsColimit (buildColimit s t hs ht i) where
  desc q := by
    refine' hi.desc (Cofork.ofπ _ _)
    · 

Proof state:
case refine'_1
C : Type u
inst✝² : Category.{v, u} C
J : Type w
inst✝¹ : SmallCategory J
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : J ⥤ C
c₁ : Cofan fun f => F.obj f.fst.1
c₂ : Cofan F.obj
s t : c₁.pt ⟶ c₂.pt
hs : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ s = F.map f.snd ≫ c₂.ι.app { as := f.fst.2 }
ht : ∀ (f : (p : J × J) × (p.1 ⟶ p.2)), c₁.ι.app { as := f } ≫ t = c₂.ι.app { as := f.fst.1 }
i : Cofork s t
t₁ : IsColimit c₁
t₂ : IsColimit c₂
hi : IsColimit i
q : Cocone F
⊢ c₂.pt ⟶ q.1

Next tactic:
refine' t₂.desc (Cofan.mk _ fun j => _)