File: Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean

full_name: CategoryTheory.Limits.WalkingParallelPair
code: /-- The type of objects for the diagram indexing a (co)equalizer. -/
inductive WalkingParallelPair : Type
  | zero
  | one
  deriving DecidableEq, Inhabited
goal: Type

full_name: CategoryTheory.Limits.instDecidableEqWalkingParallelPair
code: /-- The type of objects for the diagram indexing a (co)equalizer. -/
inductive WalkingParallelPair : Type
  | zero
  | one
  deriving DecidableEq, Inhabited
goal: DecidableEq CategoryTheory.Limits.WalkingParallelPair

full_name: CategoryTheory.Limits.WalkingParallelPair.zero
code: /-- The type of objects for the diagram indexing a (co)equalizer. -/
inductive WalkingParallelPair : Type
  | zero
  | one
  deriving DecidableEq, Inhabited
goal: CategoryTheory.Limits.WalkingParallelPair

full_name: CategoryTheory.Limits.WalkingParallelPair.one
code: /-- The type of objects for the diagram indexing a (co)equalizer. -/
inductive WalkingParallelPair : Type
  | zero
  | one
  deriving DecidableEq, Inhabited
goal: CategoryTheory.Limits.WalkingParallelPair

full_name: CategoryTheory.Limits.instInhabitedWalkingParallelPair
code: /-- The type of objects for the diagram indexing a (co)equalizer. -/
inductive WalkingParallelPair : Type
  | zero
  | one
  deriving DecidableEq, Inhabited
goal: Inhabited CategoryTheory.Limits.WalkingParallelPair

full_name: CategoryTheory.Limits.WalkingParallelPairHom
code: /-- The type family of morphisms for the diagram indexing a (co)equalizer. -/
inductive WalkingParallelPairHom : WalkingParallelPair → WalkingParallelPair → Type
  | left : WalkingParallelPairHom zero one
  | right : WalkingParallelPairHom zero one
  | id (X : WalkingParallelPair) : WalkingParallelPairHom X X
  deriving DecidableEq
goal: CategoryTheory.Limits.WalkingParallelPair → CategoryTheory.Limits.WalkingParallelPair → Type

full_name: CategoryTheory.Limits.WalkingParallelPairHom.left
code: /-- The type family of morphisms for the diagram indexing a (co)equalizer. -/
inductive WalkingParallelPairHom : WalkingParallelPair → WalkingParallelPair → Type
  | left : WalkingParallelPairHom zero one
  | right : WalkingParallelPairHom zero one
  | id (X : WalkingParallelPair) : WalkingParallelPairHom X X
  deriving DecidableEq
goal: CategoryTheory.Limits.WalkingParallelPairHom CategoryTheory.Limits.WalkingParallelPair.zero
  CategoryTheory.Limits.WalkingParallelPair.one

full_name: CategoryTheory.Limits.WalkingParallelPairHom.id
code: /-- The type family of morphisms for the diagram indexing a (co)equalizer. -/
inductive WalkingParallelPairHom : WalkingParallelPair → WalkingParallelPair → Type
  | left : WalkingParallelPairHom zero one
  | right : WalkingParallelPairHom zero one
  | id (X : WalkingParallelPair) : WalkingParallelPairHom X X
  deriving DecidableEq
goal: CategoryTheory.Limits.WalkingParallelPairHom X X

full_name: CategoryTheory.Limits.WalkingParallelPairHom.right
code: /-- The type family of morphisms for the diagram indexing a (co)equalizer. -/
inductive WalkingParallelPairHom : WalkingParallelPair → WalkingParallelPair → Type
  | left : WalkingParallelPairHom zero one
  | right : WalkingParallelPairHom zero one
  | id (X : WalkingParallelPair) : WalkingParallelPairHom X X
  deriving DecidableEq
goal: CategoryTheory.Limits.WalkingParallelPairHom CategoryTheory.Limits.WalkingParallelPair.zero
  CategoryTheory.Limits.WalkingParallelPair.one

full_name: CategoryTheory.Limits.instInhabitedWalkingParallelPairHomZeroOne
code: /-- Satisfying the inhabited linter -/
instance : Inhabited (WalkingParallelPairHom zero one) 
goal: Inhabited
  (CategoryTheory.Limits.WalkingParallelPairHom CategoryTheory.Limits.WalkingParallelPair.zero
    CategoryTheory.Limits.WalkingParallelPair.one)

full_name: CategoryTheory.Limits.WalkingParallelPairHom.comp
code: /-- Composition of morphisms in the indexing diagram for (co)equalizers. -/
def WalkingParallelPairHom.comp :
    -- Porting note: changed X Y Z to implicit to match comp fields in precategory
    ∀ {X Y Z : WalkingParallelPair} (_ : WalkingParallelPairHom X Y)
      (_ : WalkingParallelPairHom Y Z), WalkingParallelPairHom X Z
  
goal: CategoryTheory.Limits.WalkingParallelPairHom X Y →
  CategoryTheory.Limits.WalkingParallelPairHom Y Z → CategoryTheory.Limits.WalkingParallelPairHom X Z

full_name: CategoryTheory.Limits.WalkingParallelPairHom.id_comp
code: theorem WalkingParallelPairHom.id_comp
    {X Y : WalkingParallelPair} (g : WalkingParallelPairHom X Y) : comp (id X) g = g 
goal: (CategoryTheory.Limits.WalkingParallelPairHom.id X).comp g = g

full_name: CategoryTheory.Limits.WalkingParallelPairHom.comp_id
code: theorem WalkingParallelPairHom.comp_id
    {X Y : WalkingParallelPair} (f : WalkingParallelPairHom X Y) : comp f (id Y) = f 
goal: f.comp (CategoryTheory.Limits.WalkingParallelPairHom.id Y) = f

full_name: CategoryTheory.Limits.WalkingParallelPairHom.assoc
code: theorem WalkingParallelPairHom.assoc {X Y Z W : WalkingParallelPair}
    (f : WalkingParallelPairHom X Y) (g : WalkingParallelPairHom Y Z)
    (h : WalkingParallelPairHom Z W) : comp (comp f g) h = comp f (comp g h) 
goal: (f.comp g).comp h = f.comp (g.comp h)

full_name: CategoryTheory.Limits.walkingParallelPairHomCategory
code: instance walkingParallelPairHomCategory : SmallCategory WalkingParallelPair 
goal: CategoryTheory.SmallCategory CategoryTheory.Limits.WalkingParallelPair

full_name: CategoryTheory.Limits.walkingParallelPairHom_id
code: @[simp]
theorem walkingParallelPairHom_id (X : WalkingParallelPair) : WalkingParallelPairHom.id X = 𝟙 X 
goal: CategoryTheory.Limits.WalkingParallelPairHom.id X = CategoryTheory.CategoryStruct.id X

full_name: CategoryTheory.Limits.WalkingParallelPairHom.id.sizeOf_spec'
code: @[simp]
theorem WalkingParallelPairHom.id.sizeOf_spec' (X : WalkingParallelPair) :
    (WalkingParallelPairHom._sizeOf_inst X X).sizeOf (𝟙 X) = 1 + sizeOf X 
goal: sizeOf (CategoryTheory.CategoryStruct.id X) = 1 + sizeOf X

full_name: CategoryTheory.Limits.walkingParallelPairOp
code: /-- The functor `WalkingParallelPair ⥤ WalkingParallelPairᵒᵖ` sending left to left and right to
right.
-/
def walkingParallelPairOp : WalkingParallelPair ⥤ WalkingParallelPairᵒᵖ 
goal: CategoryTheory.Functor CategoryTheory.Limits.WalkingParallelPair CategoryTheory.Limits.WalkingParallelPairᵒᵖ

full_name: CategoryTheory.Limits.walkingParallelPairOp_zero
code: @[simp]
theorem walkingParallelPairOp_zero : walkingParallelPairOp.obj zero = op one 
goal: CategoryTheory.Limits.walkingParallelPairOp.obj CategoryTheory.Limits.WalkingParallelPair.zero =
  Opposite.op CategoryTheory.Limits.WalkingParallelPair.one

full_name: CategoryTheory.Limits.walkingParallelPairOp_one
code: @[simp]
theorem walkingParallelPairOp_one : walkingParallelPairOp.obj one = op zero 
goal: CategoryTheory.Limits.walkingParallelPairOp.obj CategoryTheory.Limits.WalkingParallelPair.one =
  Opposite.op CategoryTheory.Limits.WalkingParallelPair.zero

full_name: CategoryTheory.Limits.walkingParallelPairOp_left
code: @[simp]
theorem walkingParallelPairOp_left :
    walkingParallelPairOp.map left = @Quiver.Hom.op _ _ zero one left 
goal: CategoryTheory.Limits.walkingParallelPairOp.map CategoryTheory.Limits.WalkingParallelPairHom.left =
  Quiver.Hom.op CategoryTheory.Limits.WalkingParallelPairHom.left

full_name: CategoryTheory.Limits.walkingParallelPairOp_right
code: @[simp]
theorem walkingParallelPairOp_right :
    walkingParallelPairOp.map right = @Quiver.Hom.op _ _ zero one right 
goal: CategoryTheory.Limits.walkingParallelPairOp.map CategoryTheory.Limits.WalkingParallelPairHom.right =
  Quiver.Hom.op CategoryTheory.Limits.WalkingParallelPairHom.right

full_name: CategoryTheory.Limits.walkingParallelPairOpEquiv
code: /--
The equivalence `WalkingParallelPair ⥤ WalkingParallelPairᵒᵖ` sending left to left and right to
right.
-/
@[simps functor inverse]
def walkingParallelPairOpEquiv : WalkingParallelPair ≌ WalkingParallelPairᵒᵖ 
goal: CategoryTheory.Limits.WalkingParallelPair ≌ CategoryTheory.Limits.WalkingParallelPairᵒᵖ

full_name: CategoryTheory.Limits.walkingParallelPairOpEquiv_functor
code: /--
The equivalence `WalkingParallelPair ⥤ WalkingParallelPairᵒᵖ` sending left to left and right to
right.
-/
@[simps functor inverse]
def walkingParallelPairOpEquiv : WalkingParallelPair ≌ WalkingParallelPairᵒᵖ 
goal: CategoryTheory.Limits.walkingParallelPairOpEquiv.functor = CategoryTheory.Limits.walkingParallelPairOp

full_name: CategoryTheory.Limits.walkingParallelPairOpEquiv_inverse
code: /--
The equivalence `WalkingParallelPair ⥤ WalkingParallelPairᵒᵖ` sending left to left and right to
right.
-/
@[simps functor inverse]
def walkingParallelPairOpEquiv : WalkingParallelPair ≌ WalkingParallelPairᵒᵖ 
goal: CategoryTheory.Limits.walkingParallelPairOpEquiv.inverse = CategoryTheory.Limits.walkingParallelPairOp.leftOp

full_name: CategoryTheory.Limits.walkingParallelPairOpEquiv_unitIso_zero
code: @[simp]
theorem walkingParallelPairOpEquiv_unitIso_zero :
    walkingParallelPairOpEquiv.unitIso.app zero = Iso.refl zero 
goal: CategoryTheory.Limits.walkingParallelPairOpEquiv.unitIso.app CategoryTheory.Limits.WalkingParallelPair.zero =
  CategoryTheory.Iso.refl CategoryTheory.Limits.WalkingParallelPair.zero

full_name: CategoryTheory.Limits.walkingParallelPairOpEquiv_unitIso_one
code: @[simp]
theorem walkingParallelPairOpEquiv_unitIso_one :
    walkingParallelPairOpEquiv.unitIso.app one = Iso.refl one 
goal: CategoryTheory.Limits.walkingParallelPairOpEquiv.unitIso.app CategoryTheory.Limits.WalkingParallelPair.one =
  CategoryTheory.Iso.refl CategoryTheory.Limits.WalkingParallelPair.one

full_name: CategoryTheory.Limits.walkingParallelPairOpEquiv_counitIso_zero
code: @[simp]
theorem walkingParallelPairOpEquiv_counitIso_zero :
    walkingParallelPairOpEquiv.counitIso.app (op zero) = Iso.refl (op zero) 
goal: CategoryTheory.Limits.walkingParallelPairOpEquiv.counitIso.app
    (Opposite.op CategoryTheory.Limits.WalkingParallelPair.zero) =
  CategoryTheory.Iso.refl (Opposite.op CategoryTheory.Limits.WalkingParallelPair.zero)

full_name: CategoryTheory.Limits.walkingParallelPairOpEquiv_counitIso_one
code: @[simp]
theorem walkingParallelPairOpEquiv_counitIso_one :
    walkingParallelPairOpEquiv.counitIso.app (op one) = Iso.refl (op one) 
goal: CategoryTheory.Limits.walkingParallelPairOpEquiv.counitIso.app
    (Opposite.op CategoryTheory.Limits.WalkingParallelPair.one) =
  CategoryTheory.Iso.refl (Opposite.op CategoryTheory.Limits.WalkingParallelPair.one)

full_name: CategoryTheory.Limits.parallelPair
code: /-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C 
goal: CategoryTheory.Functor CategoryTheory.Limits.WalkingParallelPair C

full_name: CategoryTheory.Limits.parallelPair_obj_zero
code: @[simp]
theorem parallelPair_obj_zero (f g : X ⟶ Y) : (parallelPair f g).obj zero = X 
goal: (CategoryTheory.Limits.parallelPair f g).obj CategoryTheory.Limits.WalkingParallelPair.zero = X

full_name: CategoryTheory.Limits.parallelPair_obj_one
code: @[simp]
theorem parallelPair_obj_one (f g : X ⟶ Y) : (parallelPair f g).obj one = Y 
goal: (CategoryTheory.Limits.parallelPair f g).obj CategoryTheory.Limits.WalkingParallelPair.one = Y

full_name: CategoryTheory.Limits.parallelPair_map_left
code: @[simp]
theorem parallelPair_map_left (f g : X ⟶ Y) : (parallelPair f g).map left = f 
goal: (CategoryTheory.Limits.parallelPair f g).map CategoryTheory.Limits.WalkingParallelPairHom.left = f

full_name: CategoryTheory.Limits.parallelPair_map_right
code: @[simp]
theorem parallelPair_map_right (f g : X ⟶ Y) : (parallelPair f g).map right = g 
goal: (CategoryTheory.Limits.parallelPair f g).map CategoryTheory.Limits.WalkingParallelPairHom.right = g

full_name: CategoryTheory.Limits.parallelPair_functor_obj
code: @[simp]
theorem parallelPair_functor_obj {F : WalkingParallelPair ⥤ C} (j : WalkingParallelPair) :
    (parallelPair (F.map left) (F.map right)).obj j = F.obj j 
goal: (CategoryTheory.Limits.parallelPair (F.map CategoryTheory.Limits.WalkingParallelPairHom.left)
        (F.map CategoryTheory.Limits.WalkingParallelPairHom.right)).obj
    j =
  F.obj j

full_name: CategoryTheory.Limits.diagramIsoParallelPair_hom_app
code: /-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) 
goal: (CategoryTheory.Limits.diagramIsoParallelPair F).hom.app X = CategoryTheory.eqToHom ⋯

full_name: CategoryTheory.Limits.diagramIsoParallelPair_inv_app
code: /-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) 
goal: (CategoryTheory.Limits.diagramIsoParallelPair F).inv.app X = CategoryTheory.eqToHom ⋯

full_name: CategoryTheory.Limits.diagramIsoParallelPair
code: /-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) 
goal: F ≅
  CategoryTheory.Limits.parallelPair (F.map CategoryTheory.Limits.WalkingParallelPairHom.left)
    (F.map CategoryTheory.Limits.WalkingParallelPairHom.right)

full_name: CategoryTheory.Limits.parallelPairHom
code: /-- Construct a morphism between parallel pairs. -/
def parallelPairHom {X' Y' : C} (f g : X ⟶ Y) (f' g' : X' ⟶ Y') (p : X ⟶ X') (q : Y ⟶ Y')
    (wf : f ≫ q = p ≫ f') (wg : g ≫ q = p ≫ g') : parallelPair f g ⟶ parallelPair f' g' 
goal: CategoryTheory.Limits.parallelPair f g ⟶ CategoryTheory.Limits.parallelPair f' g'

full_name: CategoryTheory.Limits.parallelPairHom_app_zero
code: @[simp]
theorem parallelPairHom_app_zero {X' Y' : C} (f g : X ⟶ Y) (f' g' : X' ⟶ Y') (p : X ⟶ X')
    (q : Y ⟶ Y') (wf : f ≫ q = p ≫ f') (wg : g ≫ q = p ≫ g') :
    (parallelPairHom f g f' g' p q wf wg).app zero = p 
goal: (CategoryTheory.Limits.parallelPairHom f g f' g' p q wf wg).app CategoryTheory.Limits.WalkingParallelPair.zero = p

full_name: CategoryTheory.Limits.parallelPairHom_app_one
code: @[simp]
theorem parallelPairHom_app_one {X' Y' : C} (f g : X ⟶ Y) (f' g' : X' ⟶ Y') (p : X ⟶ X')
    (q : Y ⟶ Y') (wf : f ≫ q = p ≫ f') (wg : g ≫ q = p ≫ g') :
    (parallelPairHom f g f' g' p q wf wg).app one = q 
goal: (CategoryTheory.Limits.parallelPairHom f g f' g' p q wf wg).app CategoryTheory.Limits.WalkingParallelPair.one = q

full_name: CategoryTheory.Limits.parallelPair.ext
code: /-- Construct a natural isomorphism between functors out of the walking parallel pair from
its components. -/
@[simps!]
def parallelPair.ext {F G : WalkingParallelPair ⥤ C} (zero : F.obj zero ≅ G.obj zero)
    (one : F.obj one ≅ G.obj one) (left : F.map left ≫ one.hom = zero.hom ≫ G.map left)
    (right : F.map right ≫ one.hom = zero.hom ≫ G.map right) : F ≅ G 
goal: F ≅ G

full_name: CategoryTheory.Limits.parallelPair.ext_hom_app
code: /-- Construct a natural isomorphism between functors out of the walking parallel pair from
its components. -/
@[simps!]
def parallelPair.ext {F G : WalkingParallelPair ⥤ C} (zero : F.obj zero ≅ G.obj zero)
    (one : F.obj one ≅ G.obj one) (left : F.map left ≫ one.hom = zero.hom ≫ G.map left)
    (right : F.map right ≫ one.hom = zero.hom ≫ G.map right) : F ≅ G 
goal: (CategoryTheory.Limits.parallelPair.ext zero one left right).hom.app X =
  (CategoryTheory.Limits.WalkingParallelPair.rec zero one X).hom

full_name: CategoryTheory.Limits.parallelPair.ext_inv_app
code: /-- Construct a natural isomorphism between functors out of the walking parallel pair from
its components. -/
@[simps!]
def parallelPair.ext {F G : WalkingParallelPair ⥤ C} (zero : F.obj zero ≅ G.obj zero)
    (one : F.obj one ≅ G.obj one) (left : F.map left ≫ one.hom = zero.hom ≫ G.map left)
    (right : F.map right ≫ one.hom = zero.hom ≫ G.map right) : F ≅ G 
goal: (CategoryTheory.Limits.parallelPair.ext zero one left right).inv.app X =
  (CategoryTheory.Limits.WalkingParallelPair.rec zero one X).inv

full_name: CategoryTheory.Limits.parallelPair.eqOfHomEq
code: /-- Construct a natural isomorphism between `parallelPair f g` and `parallelPair f' g'` given
equalities `f = f'` and `g = g'`. -/
@[simps!]
def parallelPair.eqOfHomEq {f g f' g' : X ⟶ Y} (hf : f = f') (hg : g = g') :
    parallelPair f g ≅ parallelPair f' g' 
goal: CategoryTheory.Limits.parallelPair f g ≅ CategoryTheory.Limits.parallelPair f' g'

full_name: CategoryTheory.Limits.parallelPair.eqOfHomEq_hom_app
code: /-- Construct a natural isomorphism between `parallelPair f g` and `parallelPair f' g'` given
equalities `f = f'` and `g = g'`. -/
@[simps!]
def parallelPair.eqOfHomEq {f g f' g' : X ⟶ Y} (hf : f = f') (hg : g = g') :
    parallelPair f g ≅ parallelPair f' g' 
goal: ∀ (X_1 : CategoryTheory.Limits.WalkingParallelPair),
  (CategoryTheory.Limits.parallelPair.eqOfHomEq hf hg).hom.app X_1 =
    (CategoryTheory.Limits.WalkingParallelPair.rec (CategoryTheory.Iso.refl X) (CategoryTheory.Iso.refl Y) X_1).hom

full_name: CategoryTheory.Limits.parallelPair.eqOfHomEq_inv_app
code: /-- Construct a natural isomorphism between `parallelPair f g` and `parallelPair f' g'` given
equalities `f = f'` and `g = g'`. -/
@[simps!]
def parallelPair.eqOfHomEq {f g f' g' : X ⟶ Y} (hf : f = f') (hg : g = g') :
    parallelPair f g ≅ parallelPair f' g' 
goal: ∀ (X_1 : CategoryTheory.Limits.WalkingParallelPair),
  (CategoryTheory.Limits.parallelPair.eqOfHomEq hf hg).inv.app X_1 =
    (CategoryTheory.Limits.WalkingParallelPair.rec (CategoryTheory.Iso.refl X) (CategoryTheory.Iso.refl Y) X_1).inv

full_name: CategoryTheory.Limits.Fork
code: /-- A fork on `f` and `g` is just a `Cone (parallelPair f g)`. -/
abbrev Fork (f g : X ⟶ Y) 
goal: Type (max u v)

full_name: CategoryTheory.Limits.Cofork
code: /-- A cofork on `f` and `g` is just a `Cocone (parallelPair f g)`. -/
abbrev Cofork (f g : X ⟶ Y) 
goal: Type (max u v)

full_name: CategoryTheory.Limits.Fork.ι
code: /-- A fork `t` on the parallel pair `f g : X ⟶ Y` consists of two morphisms
    `t.π.app zero : t.pt ⟶ X`
    and `t.π.app one : t.pt ⟶ Y`. Of these, only the first one is interesting, and we give it the
    shorter name `Fork.ι t`. -/
def Fork.ι (t : Fork f g) 
goal: ((CategoryTheory.Functor.const CategoryTheory.Limits.WalkingParallelPair).obj t.pt).obj
    CategoryTheory.Limits.WalkingParallelPair.zero ⟶
  (CategoryTheory.Limits.parallelPair f g).obj CategoryTheory.Limits.WalkingParallelPair.zero

full_name: CategoryTheory.Limits.Fork.app_zero_eq_ι
code: @[simp]
theorem Fork.app_zero_eq_ι (t : Fork f g) : t.π.app zero = t.ι 
goal: t.π.app CategoryTheory.Limits.WalkingParallelPair.zero = t.ι

full_name: CategoryTheory.Limits.Cofork.π
code: /-- A cofork `t` on the parallelPair `f g : X ⟶ Y` consists of two morphisms
    `t.ι.app zero : X ⟶ t.pt` and `t.ι.app one : Y ⟶ t.pt`. Of these, only the second one is
    interesting, and we give it the shorter name `Cofork.π t`. -/
def Cofork.π (t : Cofork f g) 
goal: (CategoryTheory.Limits.parallelPair f g).obj CategoryTheory.Limits.WalkingParallelPair.one ⟶
  ((CategoryTheory.Functor.const CategoryTheory.Limits.WalkingParallelPair).obj t.pt).obj
    CategoryTheory.Limits.WalkingParallelPair.one

full_name: CategoryTheory.Limits.Cofork.app_one_eq_π
code: @[simp]
theorem Cofork.app_one_eq_π (t : Cofork f g) : t.ι.app one = t.π 
goal: t.ι.app CategoryTheory.Limits.WalkingParallelPair.one = t.π

full_name: CategoryTheory.Limits.Fork.app_one_eq_ι_comp_left
code: @[simp]
theorem Fork.app_one_eq_ι_comp_left (s : Fork f g) : s.π.app one = s.ι ≫ f 
goal: s.π.app CategoryTheory.Limits.WalkingParallelPair.one = CategoryTheory.CategoryStruct.comp s.ι f

full_name: CategoryTheory.Limits.Fork.app_one_eq_ι_comp_right
code: @[reassoc]
theorem Fork.app_one_eq_ι_comp_right (s : Fork f g) : s.π.app one = s.ι ≫ g 
goal: s.π.app CategoryTheory.Limits.WalkingParallelPair.one = CategoryTheory.CategoryStruct.comp s.ι g

full_name: CategoryTheory.Limits.Cofork.app_zero_eq_comp_π_left
code: @[simp]
theorem Cofork.app_zero_eq_comp_π_left (s : Cofork f g) : s.ι.app zero = f ≫ s.π 
goal: s.ι.app CategoryTheory.Limits.WalkingParallelPair.zero = CategoryTheory.CategoryStruct.comp f s.π

full_name: CategoryTheory.Limits.Cofork.app_zero_eq_comp_π_right
code: @[reassoc]
theorem Cofork.app_zero_eq_comp_π_right (s : Cofork f g) : s.ι.app zero = g ≫ s.π 
goal: s.ι.app CategoryTheory.Limits.WalkingParallelPair.zero = CategoryTheory.CategoryStruct.comp g s.π

full_name: CategoryTheory.Limits.Fork.ofι
code: /-- A fork on `f g : X ⟶ Y` is determined by the morphism `ι : P ⟶ X` satisfying `ι ≫ f = ι ≫ g`.
-/
@[simps]
def Fork.ofι {P : C} (ι : P ⟶ X) (w : ι ≫ f = ι ≫ g) : Fork f g 
goal: CategoryTheory.Limits.Fork f g

full_name: CategoryTheory.Limits.Fork.ofι_π_app
code: /-- A fork on `f g : X ⟶ Y` is determined by the morphism `ι : P ⟶ X` satisfying `ι ≫ f = ι ≫ g`.
-/
@[simps]
def Fork.ofι {P : C} (ι : P ⟶ X) (w : ι ≫ f = ι ≫ g) : Fork f g 
goal: ∀ (X_1 : CategoryTheory.Limits.WalkingParallelPair),
  (CategoryTheory.Limits.Fork.ofι ι w).π.app X_1 =
    CategoryTheory.Limits.WalkingParallelPair.casesOn (motive := fun t =>
      X_1 = t →
        (((CategoryTheory.Functor.const CategoryTheory.Limits.WalkingParallelPair).obj P).obj X_1 ⟶
          (CategoryTheory.Limits.parallelPair f g).obj X_1))
      X_1 (fun h => ⋯ ▸ ι) (fun h => ⋯ ▸ CategoryTheory.CategoryStruct.comp ι f) ⋯

full_name: CategoryTheory.Limits.Fork.ofι_pt
code: /-- A fork on `f g : X ⟶ Y` is determined by the morphism `ι : P ⟶ X` satisfying `ι ≫ f = ι ≫ g`.
-/
@[simps]
def Fork.ofι {P : C} (ι : P ⟶ X) (w : ι ≫ f = ι ≫ g) : Fork f g 
goal: (CategoryTheory.Limits.Fork.ofι ι w).pt = P

full_name: CategoryTheory.Limits.Cofork.ofπ
code: /-- A cofork on `f g : X ⟶ Y` is determined by the morphism `π : Y ⟶ P` satisfying
    `f ≫ π = g ≫ π`. -/
@[simps]
def Cofork.ofπ {P : C} (π : Y ⟶ P) (w : f ≫ π = g ≫ π) : Cofork f g 
goal: CategoryTheory.Limits.Cofork f g

full_name: CategoryTheory.Limits.Cofork.ofπ_pt
code: /-- A cofork on `f g : X ⟶ Y` is determined by the morphism `π : Y ⟶ P` satisfying
    `f ≫ π = g ≫ π`. -/
@[simps]
def Cofork.ofπ {P : C} (π : Y ⟶ P) (w : f ≫ π = g ≫ π) : Cofork f g 
goal: (CategoryTheory.Limits.Cofork.ofπ π w).pt = P

full_name: CategoryTheory.Limits.Cofork.ofπ_ι_app
code: /-- A cofork on `f g : X ⟶ Y` is determined by the morphism `π : Y ⟶ P` satisfying
    `f ≫ π = g ≫ π`. -/
@[simps]
def Cofork.ofπ {P : C} (π : Y ⟶ P) (w : f ≫ π = g ≫ π) : Cofork f g 
goal: ∀ (X_1 : CategoryTheory.Limits.WalkingParallelPair),
  (CategoryTheory.Limits.Cofork.ofπ π w).ι.app X_1 =
    CategoryTheory.Limits.WalkingParallelPair.casesOn X_1 (CategoryTheory.CategoryStruct.comp f π) π

full_name: CategoryTheory.Limits.Fork.ι_ofι
code: @[simp]
theorem Fork.ι_ofι {P : C} (ι : P ⟶ X) (w : ι ≫ f = ι ≫ g) : (Fork.ofι ι w).ι = ι 
goal: (CategoryTheory.Limits.Fork.ofι ι w).ι = ι

full_name: CategoryTheory.Limits.Cofork.π_ofπ
code: @[simp]
theorem Cofork.π_ofπ {P : C} (π : Y ⟶ P) (w : f ≫ π = g ≫ π) : (Cofork.ofπ π w).π = π 
goal: (CategoryTheory.Limits.Cofork.ofπ π w).π = π

full_name: CategoryTheory.Limits.Fork.condition
code: @[reassoc (attr := simp)]
theorem Fork.condition (t : Fork f g) : t.ι ≫ f = t.ι ≫ g 
goal: CategoryTheory.CategoryStruct.comp t.ι f = CategoryTheory.CategoryStruct.comp t.ι g

full_name: CategoryTheory.Limits.Cofork.condition
code: @[reassoc (attr := simp)]
theorem Cofork.condition (t : Cofork f g) : f ≫ t.π = g ≫ t.π 
goal: CategoryTheory.CategoryStruct.comp f t.π = CategoryTheory.CategoryStruct.comp g t.π

full_name: CategoryTheory.Limits.Fork.equalizer_ext
code: /-- To check whether two maps are equalized by both maps of a fork, it suffices to check it for the
    first map -/
theorem Fork.equalizer_ext (s : Fork f g) {W : C} {k l : W ⟶ s.pt} (h : k ≫ s.ι = l ≫ s.ι) :
    ∀ j : WalkingParallelPair, k ≫ s.π.app j = l ≫ s.π.app j
  
goal: CategoryTheory.CategoryStruct.comp k (s.π.app j) = CategoryTheory.CategoryStruct.comp l (s.π.app j)

full_name: CategoryTheory.Limits.Cofork.coequalizer_ext
code: /-- To check whether two maps are coequalized by both maps of a cofork, it suffices to check it for
    the second map -/
theorem Cofork.coequalizer_ext (s : Cofork f g) {W : C} {k l : s.pt ⟶ W}
    (h : Cofork.π s ≫ k = Cofork.π s ≫ l) : ∀ j : WalkingParallelPair, s.ι.app j ≫ k = s.ι.app j ≫ l
  
goal: CategoryTheory.CategoryStruct.comp (s.ι.app j) k = CategoryTheory.CategoryStruct.comp (s.ι.app j) l

full_name: CategoryTheory.Limits.Fork.IsLimit.hom_ext
code: theorem Fork.IsLimit.hom_ext {s : Fork f g} (hs : IsLimit s) {W : C} {k l : W ⟶ s.pt}
    (h : k ≫ Fork.ι s = l ≫ Fork.ι s) : k = l 
goal: k = l

full_name: CategoryTheory.Limits.Cofork.IsColimit.hom_ext
code: theorem Cofork.IsColimit.hom_ext {s : Cofork f g} (hs : IsColimit s) {W : C} {k l : s.pt ⟶ W}
    (h : Cofork.π s ≫ k = Cofork.π s ≫ l) : k = l 
goal: k = l

full_name: CategoryTheory.Limits.Fork.IsLimit.lift_ι
code: @[reassoc (attr := simp)]
theorem Fork.IsLimit.lift_ι {s t : Fork f g} (hs : IsLimit s) : hs.lift t ≫ s.ι = t.ι 
goal: CategoryTheory.CategoryStruct.comp (hs.lift t) s.ι = t.ι

full_name: CategoryTheory.Limits.Cofork.IsColimit.π_desc
code: @[reassoc (attr := simp)]
theorem Cofork.IsColimit.π_desc {s t : Cofork f g} (hs : IsColimit s) : s.π ≫ hs.desc t = t.π 
goal: CategoryTheory.CategoryStruct.comp s.π (hs.desc t) = t.π

full_name: CategoryTheory.Limits.Fork.IsLimit.lift
code: /-- If `s` is a limit fork over `f` and `g`, then a morphism `k : W ⟶ X` satisfying
    `k ≫ f = k ≫ g` induces a morphism `l : W ⟶ s.pt` such that `l ≫ fork.ι s = k`. -/
def Fork.IsLimit.lift {s : Fork f g} (hs : IsLimit s) {W : C} (k : W ⟶ X) (h : k ≫ f = k ≫ g) :
    W ⟶ s.pt 
goal: W ⟶ s.pt

full_name: CategoryTheory.Limits.Fork.IsLimit.lift_ι'
code: @[reassoc (attr := simp)]
lemma Fork.IsLimit.lift_ι' {s : Fork f g} (hs : IsLimit s) {W : C} (k : W ⟶ X) (h : k ≫ f = k ≫ g) :
    Fork.IsLimit.lift hs k h ≫ Fork.ι s = k 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.Fork.IsLimit.lift hs k h) s.ι = k

full_name: CategoryTheory.Limits.Fork.IsLimit.lift'
code: /-- If `s` is a limit fork over `f` and `g`, then a morphism `k : W ⟶ X` satisfying
    `k ≫ f = k ≫ g` induces a morphism `l : W ⟶ s.pt` such that `l ≫ fork.ι s = k`. -/
def Fork.IsLimit.lift' {s : Fork f g} (hs : IsLimit s) {W : C} (k : W ⟶ X) (h : k ≫ f = k ≫ g) :
    { l : W ⟶ s.pt // l ≫ Fork.ι s = k } 
goal: { l // CategoryTheory.CategoryStruct.comp l s.ι = k }

full_name: CategoryTheory.Limits.Cofork.IsColimit.desc
code: /-- If `s` is a colimit cofork over `f` and `g`, then a morphism `k : Y ⟶ W` satisfying
    `f ≫ k = g ≫ k` induces a morphism `l : s.pt ⟶ W` such that `cofork.π s ≫ l = k`. -/
def Cofork.IsColimit.desc {s : Cofork f g} (hs : IsColimit s) {W : C} (k : Y ⟶ W)
    (h : f ≫ k = g ≫ k) : s.pt ⟶ W 
goal: s.pt ⟶ W

full_name: CategoryTheory.Limits.Cofork.IsColimit.π_desc'
code: @[reassoc (attr := simp)]
lemma Cofork.IsColimit.π_desc' {s : Cofork f g} (hs : IsColimit s) {W : C} (k : Y ⟶ W)
    (h : f ≫ k = g ≫ k) : Cofork.π s ≫ Cofork.IsColimit.desc hs k h = k 
goal: CategoryTheory.CategoryStruct.comp s.π (CategoryTheory.Limits.Cofork.IsColimit.desc hs k h) = k

full_name: CategoryTheory.Limits.Cofork.IsColimit.desc'
code: /-- If `s` is a colimit cofork over `f` and `g`, then a morphism `k : Y ⟶ W` satisfying
    `f ≫ k = g ≫ k` induces a morphism `l : s.pt ⟶ W` such that `cofork.π s ≫ l = k`. -/
def Cofork.IsColimit.desc' {s : Cofork f g} (hs : IsColimit s) {W : C} (k : Y ⟶ W)
    (h : f ≫ k = g ≫ k) : { l : s.pt ⟶ W // Cofork.π s ≫ l = k } 
goal: { l // CategoryTheory.CategoryStruct.comp s.π l = k }

full_name: CategoryTheory.Limits.Fork.IsLimit.existsUnique
code: theorem Fork.IsLimit.existsUnique {s : Fork f g} (hs : IsLimit s) {W : C} (k : W ⟶ X)
    (h : k ≫ f = k ≫ g) : ∃! l : W ⟶ s.pt, l ≫ Fork.ι s = k 
goal: ∃! l, CategoryTheory.CategoryStruct.comp l s.ι = k

full_name: CategoryTheory.Limits.Cofork.IsColimit.existsUnique
code: theorem Cofork.IsColimit.existsUnique {s : Cofork f g} (hs : IsColimit s) {W : C} (k : Y ⟶ W)
    (h : f ≫ k = g ≫ k) : ∃! d : s.pt ⟶ W, Cofork.π s ≫ d = k 
goal: ∃! d, CategoryTheory.CategoryStruct.comp s.π d = k

full_name: CategoryTheory.Limits.Fork.IsLimit.mk
code: /-- This is a slightly more convenient method to verify that a fork is a limit cone. It
    only asks for a proof of facts that carry any mathematical content -/
@[simps]
def Fork.IsLimit.mk (t : Fork f g) (lift : ∀ s : Fork f g, s.pt ⟶ t.pt)
    (fac : ∀ s : Fork f g, lift s ≫ Fork.ι t = Fork.ι s)
    (uniq : ∀ (s : Fork f g) (m : s.pt ⟶ t.pt) (_ : m ≫ t.ι = s.ι), m = lift s) : IsLimit t 
goal: CategoryTheory.Limits.IsLimit t

full_name: CategoryTheory.Limits.Fork.IsLimit.mk_lift
code: /-- This is a slightly more convenient method to verify that a fork is a limit cone. It
    only asks for a proof of facts that carry any mathematical content -/
@[simps]
def Fork.IsLimit.mk (t : Fork f g) (lift : ∀ s : Fork f g, s.pt ⟶ t.pt)
    (fac : ∀ s : Fork f g, lift s ≫ Fork.ι t = Fork.ι s)
    (uniq : ∀ (s : Fork f g) (m : s.pt ⟶ t.pt) (_ : m ≫ t.ι = s.ι), m = lift s) : IsLimit t 
goal: (CategoryTheory.Limits.Fork.IsLimit.mk t lift fac uniq).lift s = lift s

full_name: CategoryTheory.Limits.Fork.IsLimit.mk'
code: /-- This is another convenient method to verify that a fork is a limit cone. It
    only asks for a proof of facts that carry any mathematical content, and allows access to the
    same `s` for all parts. -/
def Fork.IsLimit.mk' {X Y : C} {f g : X ⟶ Y} (t : Fork f g)
    (create : ∀ s : Fork f g, { l // l ≫ t.ι = s.ι ∧ ∀ {m}, m ≫ t.ι = s.ι → m = l }) : IsLimit t 
goal: CategoryTheory.Limits.IsLimit t

full_name: CategoryTheory.Limits.Cofork.IsColimit.mk
code: /-- This is a slightly more convenient method to verify that a cofork is a colimit cocone. It
    only asks for a proof of facts that carry any mathematical content -/
def Cofork.IsColimit.mk (t : Cofork f g) (desc : ∀ s : Cofork f g, t.pt ⟶ s.pt)
    (fac : ∀ s : Cofork f g, Cofork.π t ≫ desc s = Cofork.π s)
    (uniq : ∀ (s : Cofork f g) (m : t.pt ⟶ s.pt) (_ : t.π ≫ m = s.π), m = desc s) : IsColimit t 
goal: CategoryTheory.Limits.IsColimit t

full_name: CategoryTheory.Limits.Cofork.IsColimit.mk'
code: /-- This is another convenient method to verify that a fork is a limit cone. It
    only asks for a proof of facts that carry any mathematical content, and allows access to the
    same `s` for all parts. -/
def Cofork.IsColimit.mk' {X Y : C} {f g : X ⟶ Y} (t : Cofork f g)
    (create : ∀ s : Cofork f g, { l : t.pt ⟶ s.pt // t.π ≫ l = s.π
                                    ∧ ∀ {m}, t.π ≫ m = s.π → m = l }) : IsColimit t 
goal: CategoryTheory.Limits.IsColimit t

full_name: CategoryTheory.Limits.Fork.IsLimit.ofExistsUnique
code: /-- Noncomputably make a limit cone from the existence of unique factorizations. -/
noncomputable def Fork.IsLimit.ofExistsUnique {t : Fork f g}
    (hs : ∀ s : Fork f g, ∃! l : s.pt ⟶ t.pt, l ≫ Fork.ι t = Fork.ι s) : IsLimit t 
goal: CategoryTheory.Limits.IsLimit t

full_name: CategoryTheory.Limits.Cofork.IsColimit.ofExistsUnique
code: /-- Noncomputably make a colimit cocone from the existence of unique factorizations. -/
noncomputable def Cofork.IsColimit.ofExistsUnique {t : Cofork f g}
    (hs : ∀ s : Cofork f g, ∃! d : t.pt ⟶ s.pt, Cofork.π t ≫ d = Cofork.π s) : IsColimit t 
goal: CategoryTheory.Limits.IsColimit t

full_name: CategoryTheory.Limits.Fork.IsLimit.homIso_symm_apply
code: /--
Given a limit cone for the pair `f g : X ⟶ Y`, for any `Z`, morphisms from `Z` to its point are in
bijection with morphisms `h : Z ⟶ X` such that `h ≫ f = h ≫ g`.
Further, this bijection is natural in `Z`: see `Fork.IsLimit.homIso_natural`.
This is a special case of `IsLimit.homIso'`, often useful to construct adjunctions.
-/
@[simps]
def Fork.IsLimit.homIso {X Y : C} {f g : X ⟶ Y} {t : Fork f g} (ht : IsLimit t) (Z : C) :
    (Z ⟶ t.pt) ≃ { h : Z ⟶ X // h ≫ f = h ≫ g } 
goal: (CategoryTheory.Limits.Fork.IsLimit.homIso ht Z).symm h = ↑(CategoryTheory.Limits.Fork.IsLimit.lift' ht ↑h ⋯)

full_name: CategoryTheory.Limits.Fork.IsLimit.homIso
code: /--
Given a limit cone for the pair `f g : X ⟶ Y`, for any `Z`, morphisms from `Z` to its point are in
bijection with morphisms `h : Z ⟶ X` such that `h ≫ f = h ≫ g`.
Further, this bijection is natural in `Z`: see `Fork.IsLimit.homIso_natural`.
This is a special case of `IsLimit.homIso'`, often useful to construct adjunctions.
-/
@[simps]
def Fork.IsLimit.homIso {X Y : C} {f g : X ⟶ Y} {t : Fork f g} (ht : IsLimit t) (Z : C) :
    (Z ⟶ t.pt) ≃ { h : Z ⟶ X // h ≫ f = h ≫ g } 
goal: (Z ⟶ t.pt) ≃ { h // CategoryTheory.CategoryStruct.comp h f = CategoryTheory.CategoryStruct.comp h g }

full_name: CategoryTheory.Limits.Fork.IsLimit.homIso_apply_coe
code: /--
Given a limit cone for the pair `f g : X ⟶ Y`, for any `Z`, morphisms from `Z` to its point are in
bijection with morphisms `h : Z ⟶ X` such that `h ≫ f = h ≫ g`.
Further, this bijection is natural in `Z`: see `Fork.IsLimit.homIso_natural`.
This is a special case of `IsLimit.homIso'`, often useful to construct adjunctions.
-/
@[simps]
def Fork.IsLimit.homIso {X Y : C} {f g : X ⟶ Y} {t : Fork f g} (ht : IsLimit t) (Z : C) :
    (Z ⟶ t.pt) ≃ { h : Z ⟶ X // h ≫ f = h ≫ g } 
goal: ↑((CategoryTheory.Limits.Fork.IsLimit.homIso ht Z) k) = CategoryTheory.CategoryStruct.comp k t.ι

full_name: CategoryTheory.Limits.Fork.IsLimit.homIso_natural
code: /-- The bijection of `Fork.IsLimit.homIso` is natural in `Z`. -/
theorem Fork.IsLimit.homIso_natural {X Y : C} {f g : X ⟶ Y} {t : Fork f g} (ht : IsLimit t)
    {Z Z' : C} (q : Z' ⟶ Z) (k : Z ⟶ t.pt) :
    (Fork.IsLimit.homIso ht _ (q ≫ k) : Z' ⟶ X) = q ≫ (Fork.IsLimit.homIso ht _ k : Z ⟶ X) 
goal: ↑((CategoryTheory.Limits.Fork.IsLimit.homIso ht Z') (CategoryTheory.CategoryStruct.comp q k)) =
  CategoryTheory.CategoryStruct.comp q ↑((CategoryTheory.Limits.Fork.IsLimit.homIso ht Z) k)

full_name: CategoryTheory.Limits.Cofork.IsColimit.homIso_apply_coe
code: /-- Given a colimit cocone for the pair `f g : X ⟶ Y`, for any `Z`, morphisms from the cocone point
to `Z` are in bijection with morphisms `h : Y ⟶ Z` such that `f ≫ h = g ≫ h`.
Further, this bijection is natural in `Z`: see `Cofork.IsColimit.homIso_natural`.
This is a special case of `IsColimit.homIso'`, often useful to construct adjunctions.
-/
@[simps]
def Cofork.IsColimit.homIso {X Y : C} {f g : X ⟶ Y} {t : Cofork f g} (ht : IsColimit t) (Z : C) :
    (t.pt ⟶ Z) ≃ { h : Y ⟶ Z // f ≫ h = g ≫ h } 
goal: ↑((CategoryTheory.Limits.Cofork.IsColimit.homIso ht Z) k) = CategoryTheory.CategoryStruct.comp t.π k

full_name: CategoryTheory.Limits.Cofork.IsColimit.homIso_symm_apply
code: /-- Given a colimit cocone for the pair `f g : X ⟶ Y`, for any `Z`, morphisms from the cocone point
to `Z` are in bijection with morphisms `h : Y ⟶ Z` such that `f ≫ h = g ≫ h`.
Further, this bijection is natural in `Z`: see `Cofork.IsColimit.homIso_natural`.
This is a special case of `IsColimit.homIso'`, often useful to construct adjunctions.
-/
@[simps]
def Cofork.IsColimit.homIso {X Y : C} {f g : X ⟶ Y} {t : Cofork f g} (ht : IsColimit t) (Z : C) :
    (t.pt ⟶ Z) ≃ { h : Y ⟶ Z // f ≫ h = g ≫ h } 
goal: (CategoryTheory.Limits.Cofork.IsColimit.homIso ht Z).symm h = ↑(CategoryTheory.Limits.Cofork.IsColimit.desc' ht ↑h ⋯)

full_name: CategoryTheory.Limits.Cofork.IsColimit.homIso
code: /-- Given a colimit cocone for the pair `f g : X ⟶ Y`, for any `Z`, morphisms from the cocone point
to `Z` are in bijection with morphisms `h : Y ⟶ Z` such that `f ≫ h = g ≫ h`.
Further, this bijection is natural in `Z`: see `Cofork.IsColimit.homIso_natural`.
This is a special case of `IsColimit.homIso'`, often useful to construct adjunctions.
-/
@[simps]
def Cofork.IsColimit.homIso {X Y : C} {f g : X ⟶ Y} {t : Cofork f g} (ht : IsColimit t) (Z : C) :
    (t.pt ⟶ Z) ≃ { h : Y ⟶ Z // f ≫ h = g ≫ h } 
goal: (t.pt ⟶ Z) ≃ { h // CategoryTheory.CategoryStruct.comp f h = CategoryTheory.CategoryStruct.comp g h }

full_name: CategoryTheory.Limits.Cofork.IsColimit.homIso_natural
code: /-- The bijection of `Cofork.IsColimit.homIso` is natural in `Z`. -/
theorem Cofork.IsColimit.homIso_natural {X Y : C} {f g : X ⟶ Y} {t : Cofork f g} {Z Z' : C}
    (q : Z ⟶ Z') (ht : IsColimit t) (k : t.pt ⟶ Z) :
    (Cofork.IsColimit.homIso ht _ (k ≫ q) : Y ⟶ Z') =
      (Cofork.IsColimit.homIso ht _ k : Y ⟶ Z) ≫ q 
goal: ↑((CategoryTheory.Limits.Cofork.IsColimit.homIso ht Z') (CategoryTheory.CategoryStruct.comp k q)) =
  CategoryTheory.CategoryStruct.comp (↑((CategoryTheory.Limits.Cofork.IsColimit.homIso ht Z) k)) q

full_name: CategoryTheory.Limits.Cone.ofFork
code: /-- This is a helper construction that can be useful when verifying that a category has all
    equalizers. Given `F : WalkingParallelPair ⥤ C`, which is really the same as
    `parallelPair (F.map left) (F.map right)`, and a fork on `F.map left` and `F.map right`,
    we get a cone on `F`.

    If you're thinking about using this, have a look at `hasEqualizers_of_hasLimit_parallelPair`,
    which you may find to be an easier way of achieving your goal. -/
def Cone.ofFork {F : WalkingParallelPair ⥤ C} (t : Fork (F.map left) (F.map right)) : Cone F 
goal: CategoryTheory.Limits.Cone F

full_name: CategoryTheory.Limits.Cocone.ofCofork
code: /-- This is a helper construction that can be useful when verifying that a category has all
    coequalizers. Given `F : WalkingParallelPair ⥤ C`, which is really the same as
    `parallelPair (F.map left) (F.map right)`, and a cofork on `F.map left` and `F.map right`,
    we get a cocone on `F`.

    If you're thinking about using this, have a look at
    `hasCoequalizers_of_hasColimit_parallelPair`, which you may find to be an easier way of
    achieving your goal. -/
def Cocone.ofCofork {F : WalkingParallelPair ⥤ C} (t : Cofork (F.map left) (F.map right)) :
    Cocone F 
goal: CategoryTheory.Limits.Cocone F

full_name: CategoryTheory.Limits.Cone.ofFork_π
code: @[simp]
theorem Cone.ofFork_π {F : WalkingParallelPair ⥤ C} (t : Fork (F.map left) (F.map right)) (j) :
    (Cone.ofFork t).π.app j = t.π.app j ≫ eqToHom (by aesop) 
goal: (CategoryTheory.Limits.Cone.ofFork t).π.app j =
  CategoryTheory.CategoryStruct.comp (t.π.app j) (CategoryTheory.eqToHom ⋯)

full_name: CategoryTheory.Limits.Cocone.ofCofork_ι
code: @[simp]
theorem Cocone.ofCofork_ι {F : WalkingParallelPair ⥤ C} (t : Cofork (F.map left) (F.map right))
    (j) : (Cocone.ofCofork t).ι.app j = eqToHom (by aesop) ≫ t.ι.app j 
goal: (CategoryTheory.Limits.Cocone.ofCofork t).ι.app j =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.eqToHom ⋯) (t.ι.app j)

full_name: CategoryTheory.Limits.Fork.ofCone
code: /-- Given `F : WalkingParallelPair ⥤ C`, which is really the same as
    `parallelPair (F.map left) (F.map right)` and a cone on `F`, we get a fork on
    `F.map left` and `F.map right`. -/
def Fork.ofCone {F : WalkingParallelPair ⥤ C} (t : Cone F) : Fork (F.map left) (F.map right) 
goal: CategoryTheory.Limits.Fork (F.map CategoryTheory.Limits.WalkingParallelPairHom.left)
  (F.map CategoryTheory.Limits.WalkingParallelPairHom.right)

full_name: CategoryTheory.Limits.Cofork.ofCocone
code: /-- Given `F : WalkingParallelPair ⥤ C`, which is really the same as
    `parallelPair (F.map left) (F.map right)` and a cocone on `F`, we get a cofork on
    `F.map left` and `F.map right`. -/
def Cofork.ofCocone {F : WalkingParallelPair ⥤ C} (t : Cocone F) :
    Cofork (F.map left) (F.map right) 
goal: CategoryTheory.Limits.Cofork (F.map CategoryTheory.Limits.WalkingParallelPairHom.left)
  (F.map CategoryTheory.Limits.WalkingParallelPairHom.right)

full_name: CategoryTheory.Limits.Fork.ofCone_π
code: @[simp]
theorem Fork.ofCone_π {F : WalkingParallelPair ⥤ C} (t : Cone F) (j) :
    (Fork.ofCone t).π.app j = t.π.app j ≫ eqToHom (by aesop) 
goal: (CategoryTheory.Limits.Fork.ofCone t).π.app j =
  CategoryTheory.CategoryStruct.comp (t.π.app j) (CategoryTheory.eqToHom ⋯)

full_name: CategoryTheory.Limits.Cofork.ofCocone_ι
code: @[simp]
theorem Cofork.ofCocone_ι {F : WalkingParallelPair ⥤ C} (t : Cocone F) (j) :
    (Cofork.ofCocone t).ι.app j = eqToHom (by aesop) ≫ t.ι.app j 
goal: (CategoryTheory.Limits.Cofork.ofCocone t).ι.app j =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.eqToHom ⋯) (t.ι.app j)

full_name: CategoryTheory.Limits.Fork.ι_postcompose
code: @[simp]
theorem Fork.ι_postcompose {f' g' : X ⟶ Y} {α : parallelPair f g ⟶ parallelPair f' g'}
    {c : Fork f g} : Fork.ι ((Cones.postcompose α).obj c) = c.ι ≫ α.app _ 
goal: CategoryTheory.Limits.Fork.ι ((CategoryTheory.Limits.Cones.postcompose α).obj c) =
  CategoryTheory.CategoryStruct.comp c.ι (α.app CategoryTheory.Limits.WalkingParallelPair.zero)

full_name: CategoryTheory.Limits.Cofork.π_precompose
code: @[simp]
theorem Cofork.π_precompose {f' g' : X ⟶ Y} {α : parallelPair f g ⟶ parallelPair f' g'}
    {c : Cofork f' g'} : Cofork.π ((Cocones.precompose α).obj c) = α.app _ ≫ c.π 
goal: CategoryTheory.Limits.Cofork.π ((CategoryTheory.Limits.Cocones.precompose α).obj c) =
  CategoryTheory.CategoryStruct.comp (α.app CategoryTheory.Limits.WalkingParallelPair.one) c.π

full_name: CategoryTheory.Limits.Fork.mkHom
code: /-- Helper function for constructing morphisms between equalizer forks.
-/
@[simps]
def Fork.mkHom {s t : Fork f g} (k : s.pt ⟶ t.pt) (w : k ≫ t.ι = s.ι) : s ⟶ t 
goal: s ⟶ t

full_name: CategoryTheory.Limits.Fork.mkHom_hom
code: /-- Helper function for constructing morphisms between equalizer forks.
-/
@[simps]
def Fork.mkHom {s t : Fork f g} (k : s.pt ⟶ t.pt) (w : k ≫ t.ι = s.ι) : s ⟶ t 
goal: (CategoryTheory.Limits.Fork.mkHom k w).hom = k

full_name: CategoryTheory.Limits.Fork.ext_inv
code: /-- To construct an isomorphism between forks,
it suffices to give an isomorphism between the cone points
and check that it commutes with the `ι` morphisms.
-/
@[simps]
def Fork.ext {s t : Fork f g} (i : s.pt ≅ t.pt) (w : i.hom ≫ t.ι = s.ι := by aesop_cat) :
    s ≅ t 
goal: (CategoryTheory.Limits.Fork.ext i w).inv = CategoryTheory.Limits.Fork.mkHom i.inv ⋯

full_name: CategoryTheory.Limits.Fork.ext_hom
code: /-- To construct an isomorphism between forks,
it suffices to give an isomorphism between the cone points
and check that it commutes with the `ι` morphisms.
-/
@[simps]
def Fork.ext {s t : Fork f g} (i : s.pt ≅ t.pt) (w : i.hom ≫ t.ι = s.ι := by aesop_cat) :
    s ≅ t 
goal: (CategoryTheory.Limits.Fork.ext i w).hom = CategoryTheory.Limits.Fork.mkHom i.hom w

full_name: CategoryTheory.Limits.Fork.ext
code: /-- To construct an isomorphism between forks,
it suffices to give an isomorphism between the cone points
and check that it commutes with the `ι` morphisms.
-/
@[simps]
def Fork.ext {s t : Fork f g} (i : s.pt ≅ t.pt) (w : i.hom ≫ t.ι = s.ι := by aesop_cat) :
    s ≅ t 
goal: s ≅ t

full_name: CategoryTheory.Limits.ForkOfι.ext
code: /-- Two forks of the form `ofι` are isomorphic whenever their `ι`'s are equal. -/
def ForkOfι.ext {P : C} {ι ι' : P ⟶ X} (w : ι ≫ f = ι ≫ g) (w' : ι' ≫ f = ι' ≫ g) (h : ι = ι') :
    Fork.ofι ι w ≅ Fork.ofι ι' w' 
goal: CategoryTheory.Limits.Fork.ofι ι w ≅ CategoryTheory.Limits.Fork.ofι ι' w'

full_name: CategoryTheory.Limits.Fork.isoForkOfι
code: /-- Every fork is isomorphic to one of the form `Fork.of_ι _ _`. -/
def Fork.isoForkOfι (c : Fork f g) : c ≅ Fork.ofι c.ι c.condition 
goal: c ≅ CategoryTheory.Limits.Fork.ofι c.ι ⋯

full_name: CategoryTheory.Limits.Fork.isLimitOfIsos
code: /--
Given two forks with isomorphic components in such a way that the natural diagrams commute, then if
one is a limit, then the other one is as well.
-/
def Fork.isLimitOfIsos {X' Y' : C} (c : Fork f g) (hc : IsLimit c)
    {f' g' : X' ⟶ Y'} (c' : Fork f' g')
    (e₀ : X ≅ X') (e₁ : Y ≅ Y') (e : c.pt ≅ c'.pt)
    (comm₁ : e₀.hom ≫ f' = f ≫ e₁.hom := by aesop_cat)
    (comm₂ : e₀.hom ≫ g' = g ≫ e₁.hom := by aesop_cat)
    (comm₃ : e.hom ≫ c'.ι = c.ι ≫ e₀.hom := by aesop_cat) : IsLimit c' 
goal: CategoryTheory.Limits.IsLimit c'

full_name: CategoryTheory.Limits.Cofork.mkHom_hom
code: /-- Helper function for constructing morphisms between coequalizer coforks.
-/
@[simps]
def Cofork.mkHom {s t : Cofork f g} (k : s.pt ⟶ t.pt) (w : s.π ≫ k = t.π) : s ⟶ t 
goal: (CategoryTheory.Limits.Cofork.mkHom k w).hom = k

full_name: CategoryTheory.Limits.Cofork.mkHom
code: /-- Helper function for constructing morphisms between coequalizer coforks.
-/
@[simps]
def Cofork.mkHom {s t : Cofork f g} (k : s.pt ⟶ t.pt) (w : s.π ≫ k = t.π) : s ⟶ t 
goal: s ⟶ t

full_name: CategoryTheory.Limits.Fork.hom_comp_ι
code: @[reassoc (attr := simp)]
theorem Fork.hom_comp_ι {s t : Fork f g} (f : s ⟶ t) : f.hom ≫ t.ι = s.ι 
goal: ∀ (f_1 : s ⟶ t), CategoryTheory.CategoryStruct.comp f_1.hom t.ι = s.ι

full_name: CategoryTheory.Limits.Fork.π_comp_hom
code: @[reassoc (attr := simp)]
theorem Fork.π_comp_hom {s t : Cofork f g} (f : s ⟶ t) : s.π ≫ f.hom = t.π 
goal: ∀ (f_1 : s ⟶ t), CategoryTheory.CategoryStruct.comp s.π f_1.hom = t.π

full_name: CategoryTheory.Limits.Cofork.ext_hom
code: /-- To construct an isomorphism between coforks,
it suffices to give an isomorphism between the cocone points
and check that it commutes with the `π` morphisms.
-/
@[simps]
def Cofork.ext {s t : Cofork f g} (i : s.pt ≅ t.pt) (w : s.π ≫ i.hom = t.π := by aesop_cat) :
    s ≅ t 
goal: (CategoryTheory.Limits.Cofork.ext i w).hom = CategoryTheory.Limits.Cofork.mkHom i.hom w

full_name: CategoryTheory.Limits.Cofork.ext
code: /-- To construct an isomorphism between coforks,
it suffices to give an isomorphism between the cocone points
and check that it commutes with the `π` morphisms.
-/
@[simps]
def Cofork.ext {s t : Cofork f g} (i : s.pt ≅ t.pt) (w : s.π ≫ i.hom = t.π := by aesop_cat) :
    s ≅ t 
goal: s ≅ t

full_name: CategoryTheory.Limits.Cofork.ext_inv
code: /-- To construct an isomorphism between coforks,
it suffices to give an isomorphism between the cocone points
and check that it commutes with the `π` morphisms.
-/
@[simps]
def Cofork.ext {s t : Cofork f g} (i : s.pt ≅ t.pt) (w : s.π ≫ i.hom = t.π := by aesop_cat) :
    s ≅ t 
goal: (CategoryTheory.Limits.Cofork.ext i w).inv = CategoryTheory.Limits.Cofork.mkHom i.inv ⋯

full_name: CategoryTheory.Limits.Cofork.isoCoforkOfπ
code: /-- Every cofork is isomorphic to one of the form `Cofork.ofπ _ _`. -/
def Cofork.isoCoforkOfπ (c : Cofork f g) : c ≅ Cofork.ofπ c.π c.condition 
goal: c ≅ CategoryTheory.Limits.Cofork.ofπ c.π ⋯

full_name: CategoryTheory.Limits.HasEqualizer
code: /-- `HasEqualizer f g` represents a particular choice of limiting cone
for the parallel pair of morphisms `f` and `g`.
-/
abbrev HasEqualizer 
goal: Prop

full_name: CategoryTheory.Limits.equalizer
code: /-- If an equalizer of `f` and `g` exists, we can access an arbitrary choice of such by
    saying `equalizer f g`. -/
noncomputable abbrev equalizer : C 
goal: C

full_name: CategoryTheory.Limits.equalizer.ι
code: /-- If an equalizer of `f` and `g` exists, we can access the inclusion
    `equalizer f g ⟶ X` by saying `equalizer.ι f g`. -/
noncomputable abbrev equalizer.ι : equalizer f g ⟶ X 
goal: CategoryTheory.Limits.equalizer f g ⟶ X

full_name: CategoryTheory.Limits.equalizer.fork
code: /-- An equalizer cone for a parallel pair `f` and `g` -/
noncomputable abbrev equalizer.fork : Fork f g 
goal: CategoryTheory.Limits.Fork f g

full_name: CategoryTheory.Limits.equalizer.fork_ι
code: @[simp]
theorem equalizer.fork_ι : (equalizer.fork f g).ι = equalizer.ι f g 
goal: (CategoryTheory.Limits.equalizer.fork f g).ι = CategoryTheory.Limits.equalizer.ι f g

full_name: CategoryTheory.Limits.equalizer.fork_π_app_zero
code: @[simp]
theorem equalizer.fork_π_app_zero : (equalizer.fork f g).π.app zero = equalizer.ι f g 
goal: (CategoryTheory.Limits.equalizer.fork f g).π.app CategoryTheory.Limits.WalkingParallelPair.zero =
  CategoryTheory.Limits.equalizer.ι f g

full_name: CategoryTheory.Limits.equalizer.condition
code: @[reassoc]
theorem equalizer.condition : equalizer.ι f g ≫ f = equalizer.ι f g ≫ g 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.equalizer.ι f g) f =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.equalizer.ι f g) g

full_name: CategoryTheory.Limits.equalizerIsEqualizer
code: /-- The equalizer built from `equalizer.ι f g` is limiting. -/
noncomputable def equalizerIsEqualizer : IsLimit (Fork.ofι (equalizer.ι f g)
    (equalizer.condition f g)) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.Fork.ofι (CategoryTheory.Limits.equalizer.ι f g) ⋯)

full_name: CategoryTheory.Limits.equalizer.lift
code: /-- A morphism `k : W ⟶ X` satisfying `k ≫ f = k ≫ g` factors through the equalizer of `f` and `g`
    via `equalizer.lift : W ⟶ equalizer f g`. -/
noncomputable abbrev equalizer.lift {W : C} (k : W ⟶ X) (h : k ≫ f = k ≫ g) : W ⟶ equalizer f g 
goal: W ⟶ CategoryTheory.Limits.equalizer f g

full_name: CategoryTheory.Limits.equalizer.lift_ι
code: @[reassoc]
theorem equalizer.lift_ι {W : C} (k : W ⟶ X) (h : k ≫ f = k ≫ g) :
    equalizer.lift k h ≫ equalizer.ι f g = k 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.equalizer.lift k h) (CategoryTheory.Limits.equalizer.ι f g) =
  k

full_name: CategoryTheory.Limits.equalizer.lift'
code: /-- A morphism `k : W ⟶ X` satisfying `k ≫ f = k ≫ g` induces a morphism `l : W ⟶ equalizer f g`
    satisfying `l ≫ equalizer.ι f g = k`. -/
noncomputable def equalizer.lift' {W : C} (k : W ⟶ X) (h : k ≫ f = k ≫ g) :
    { l : W ⟶ equalizer f g // l ≫ equalizer.ι f g = k } 
goal: { l // CategoryTheory.CategoryStruct.comp l (CategoryTheory.Limits.equalizer.ι f g) = k }

full_name: CategoryTheory.Limits.equalizer.hom_ext
code: /-- Two maps into an equalizer are equal if they are equal when composed with the equalizer map. -/
@[ext]
theorem equalizer.hom_ext {W : C} {k l : W ⟶ equalizer f g}
    (h : k ≫ equalizer.ι f g = l ≫ equalizer.ι f g) : k = l 
goal: k = l

full_name: CategoryTheory.Limits.equalizer.existsUnique
code: theorem equalizer.existsUnique {W : C} (k : W ⟶ X) (h : k ≫ f = k ≫ g) :
    ∃! l : W ⟶ equalizer f g, l ≫ equalizer.ι f g = k 
goal: ∃! l, CategoryTheory.CategoryStruct.comp l (CategoryTheory.Limits.equalizer.ι f g) = k

full_name: CategoryTheory.Limits.equalizer.ι_mono
code: /-- An equalizer morphism is a monomorphism -/
instance equalizer.ι_mono : Mono (equalizer.ι f g) 
goal: CategoryTheory.Mono (CategoryTheory.Limits.equalizer.ι f g)

full_name: CategoryTheory.Limits.mono_of_isLimit_fork
code: /-- The equalizer morphism in any limit cone is a monomorphism. -/
theorem mono_of_isLimit_fork {c : Fork f g} (i : IsLimit c) : Mono (Fork.ι c) 
goal: CategoryTheory.Mono c.ι

full_name: CategoryTheory.Limits.idFork
code: /-- The identity determines a cone on the equalizer diagram of `f` and `g` if `f = g`. -/
def idFork (h : f = g) : Fork f g 
goal: CategoryTheory.Limits.Fork f g

full_name: CategoryTheory.Limits.isLimitIdFork
code: /-- The identity on `X` is an equalizer of `(f, g)`, if `f = g`. -/
def isLimitIdFork (h : f = g) : IsLimit (idFork h) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.idFork h)

full_name: CategoryTheory.Limits.isIso_limit_cone_parallelPair_of_eq
code: /-- Every equalizer of `(f, g)`, where `f = g`, is an isomorphism. -/
theorem isIso_limit_cone_parallelPair_of_eq (h₀ : f = g) {c : Fork f g} (h : IsLimit c) :
    IsIso c.ι 
goal: CategoryTheory.IsIso c.ι

full_name: CategoryTheory.Limits.equalizer.ι_of_eq
code: /-- The equalizer of `(f, g)`, where `f = g`, is an isomorphism. -/
theorem equalizer.ι_of_eq [HasEqualizer f g] (h : f = g) : IsIso (equalizer.ι f g) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.equalizer.ι f g)

full_name: CategoryTheory.Limits.isIso_limit_cone_parallelPair_of_self
code: /-- Every equalizer of `(f, f)` is an isomorphism. -/
theorem isIso_limit_cone_parallelPair_of_self {c : Fork f f} (h : IsLimit c) : IsIso c.ι 
goal: CategoryTheory.IsIso c.ι

full_name: CategoryTheory.Limits.isIso_limit_cone_parallelPair_of_epi
code: /-- An equalizer that is an epimorphism is an isomorphism. -/
theorem isIso_limit_cone_parallelPair_of_epi {c : Fork f g} (h : IsLimit c) [Epi c.ι] : IsIso c.ι 
goal: CategoryTheory.IsIso c.ι

full_name: CategoryTheory.Limits.eq_of_epi_fork_ι
code: /-- Two morphisms are equal if there is a fork whose inclusion is epi. -/
theorem eq_of_epi_fork_ι (t : Fork f g) [Epi (Fork.ι t)] : f = g 
goal: f = g

full_name: CategoryTheory.Limits.eq_of_epi_equalizer
code: /-- If the equalizer of two morphisms is an epimorphism, then the two morphisms are equal. -/
theorem eq_of_epi_equalizer [HasEqualizer f g] [Epi (equalizer.ι f g)] : f = g 
goal: f = g

full_name: CategoryTheory.Limits.hasEqualizer_of_self
code: instance hasEqualizer_of_self : HasEqualizer f f 
goal: CategoryTheory.Limits.HasEqualizer f f

full_name: CategoryTheory.Limits.equalizer.ι_of_self
code: /-- The equalizer inclusion for `(f, f)` is an isomorphism. -/
instance equalizer.ι_of_self : IsIso (equalizer.ι f f) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.equalizer.ι f f)

full_name: CategoryTheory.Limits.equalizer.isoSourceOfSelf
code: /-- The equalizer of a morphism with itself is isomorphic to the source. -/
noncomputable def equalizer.isoSourceOfSelf : equalizer f f ≅ X 
goal: CategoryTheory.Limits.equalizer f f ≅ X

full_name: CategoryTheory.Limits.equalizer.isoSourceOfSelf_hom
code: @[simp]
theorem equalizer.isoSourceOfSelf_hom : (equalizer.isoSourceOfSelf f).hom = equalizer.ι f f 
goal: (CategoryTheory.Limits.equalizer.isoSourceOfSelf f).hom = CategoryTheory.Limits.equalizer.ι f f

full_name: CategoryTheory.Limits.equalizer.isoSourceOfSelf_inv
code: @[simp]
theorem equalizer.isoSourceOfSelf_inv :
    (equalizer.isoSourceOfSelf f).inv = equalizer.lift (𝟙 X) (by simp) 
goal: (CategoryTheory.Limits.equalizer.isoSourceOfSelf f).inv =
  CategoryTheory.Limits.equalizer.lift (CategoryTheory.CategoryStruct.id X) ⋯

full_name: CategoryTheory.Limits.HasCoequalizer
code: /-- `HasCoequalizer f g` represents a particular choice of colimiting cocone
for the parallel pair of morphisms `f` and `g`.
-/
abbrev HasCoequalizer 
goal: Prop

full_name: CategoryTheory.Limits.coequalizer
code: /-- If a coequalizer of `f` and `g` exists, we can access an arbitrary choice of such by
    saying `coequalizer f g`. -/
noncomputable abbrev coequalizer : C 
goal: C

full_name: CategoryTheory.Limits.coequalizer.π
code: /-- If a coequalizer of `f` and `g` exists, we can access the corresponding projection by
    saying `coequalizer.π f g`. -/
noncomputable abbrev coequalizer.π : Y ⟶ coequalizer f g 
goal: Y ⟶ CategoryTheory.Limits.coequalizer f g

full_name: CategoryTheory.Limits.coequalizer.cofork
code: /-- An arbitrary choice of coequalizer cocone for a parallel pair `f` and `g`.
-/
noncomputable abbrev coequalizer.cofork : Cofork f g 
goal: CategoryTheory.Limits.Cofork f g

full_name: CategoryTheory.Limits.coequalizer.cofork_π
code: @[simp]
theorem coequalizer.cofork_π : (coequalizer.cofork f g).π = coequalizer.π f g 
goal: (CategoryTheory.Limits.coequalizer.cofork f g).π = CategoryTheory.Limits.coequalizer.π f g

full_name: CategoryTheory.Limits.coequalizer.cofork_ι_app_one
code: theorem coequalizer.cofork_ι_app_one : (coequalizer.cofork f g).ι.app one = coequalizer.π f g 
goal: (CategoryTheory.Limits.coequalizer.cofork f g).ι.app CategoryTheory.Limits.WalkingParallelPair.one =
  CategoryTheory.Limits.coequalizer.π f g

full_name: CategoryTheory.Limits.coequalizer.condition
code: @[reassoc]
theorem coequalizer.condition : f ≫ coequalizer.π f g = g ≫ coequalizer.π f g 
goal: CategoryTheory.CategoryStruct.comp f (CategoryTheory.Limits.coequalizer.π f g) =
  CategoryTheory.CategoryStruct.comp g (CategoryTheory.Limits.coequalizer.π f g)

full_name: CategoryTheory.Limits.coequalizerIsCoequalizer
code: /-- The cofork built from `coequalizer.π f g` is colimiting. -/
noncomputable def coequalizerIsCoequalizer :
    IsColimit (Cofork.ofπ (coequalizer.π f g) (coequalizer.condition f g)) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.Cofork.ofπ (CategoryTheory.Limits.coequalizer.π f g) ⋯)

full_name: CategoryTheory.Limits.coequalizer.desc
code: /-- Any morphism `k : Y ⟶ W` satisfying `f ≫ k = g ≫ k` factors through the coequalizer of `f`
    and `g` via `coequalizer.desc : coequalizer f g ⟶ W`. -/
noncomputable abbrev coequalizer.desc {W : C} (k : Y ⟶ W) (h : f ≫ k = g ≫ k) :
    coequalizer f g ⟶ W 
goal: CategoryTheory.Limits.coequalizer f g ⟶ W

full_name: CategoryTheory.Limits.coequalizer.π_desc
code: @[reassoc]
theorem coequalizer.π_desc {W : C} (k : Y ⟶ W) (h : f ≫ k = g ≫ k) :
    coequalizer.π f g ≫ coequalizer.desc k h = k 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.coequalizer.π f g)
    (CategoryTheory.Limits.coequalizer.desc k h) =
  k

full_name: CategoryTheory.Limits.coequalizer.π_colimMap_desc
code: theorem coequalizer.π_colimMap_desc {X' Y' Z : C} (f' g' : X' ⟶ Y') [HasCoequalizer f' g']
    (p : X ⟶ X') (q : Y ⟶ Y') (wf : f ≫ q = p ≫ f') (wg : g ≫ q = p ≫ g') (h : Y' ⟶ Z)
    (wh : f' ≫ h = g' ≫ h) :
    coequalizer.π f g ≫ colimMap (parallelPairHom f g f' g' p q wf wg) ≫ coequalizer.desc h wh =
      q ≫ h 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.coequalizer.π f g)
    (CategoryTheory.CategoryStruct.comp
      (CategoryTheory.Limits.colimMap (CategoryTheory.Limits.parallelPairHom f g f' g' p q wf wg))
      (CategoryTheory.Limits.coequalizer.desc h wh)) =
  CategoryTheory.CategoryStruct.comp q h

full_name: CategoryTheory.Limits.coequalizer.desc'
code: /-- Any morphism `k : Y ⟶ W` satisfying `f ≫ k = g ≫ k` induces a morphism
    `l : coequalizer f g ⟶ W` satisfying `coequalizer.π ≫ g = l`. -/
noncomputable def coequalizer.desc' {W : C} (k : Y ⟶ W) (h : f ≫ k = g ≫ k) :
    { l : coequalizer f g ⟶ W // coequalizer.π f g ≫ l = k } 
goal: { l // CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.coequalizer.π f g) l = k }

full_name: CategoryTheory.Limits.coequalizer.hom_ext
code: /-- Two maps from a coequalizer are equal if they are equal when composed with the coequalizer
    map -/
@[ext]
theorem coequalizer.hom_ext {W : C} {k l : coequalizer f g ⟶ W}
    (h : coequalizer.π f g ≫ k = coequalizer.π f g ≫ l) : k = l 
goal: k = l

full_name: CategoryTheory.Limits.coequalizer.existsUnique
code: theorem coequalizer.existsUnique {W : C} (k : Y ⟶ W) (h : f ≫ k = g ≫ k) :
    ∃! d : coequalizer f g ⟶ W, coequalizer.π f g ≫ d = k 
goal: ∃! d, CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.coequalizer.π f g) d = k

full_name: CategoryTheory.Limits.coequalizer.π_epi
code: /-- A coequalizer morphism is an epimorphism -/
instance coequalizer.π_epi : Epi (coequalizer.π f g) 
goal: CategoryTheory.Epi (CategoryTheory.Limits.coequalizer.π f g)

full_name: CategoryTheory.Limits.epi_of_isColimit_cofork
code: /-- The coequalizer morphism in any colimit cocone is an epimorphism. -/
theorem epi_of_isColimit_cofork {c : Cofork f g} (i : IsColimit c) : Epi c.π 
goal: CategoryTheory.Epi c.π

full_name: CategoryTheory.Limits.idCofork
code: /-- The identity determines a cocone on the coequalizer diagram of `f` and `g`, if `f = g`. -/
def idCofork (h : f = g) : Cofork f g 
goal: CategoryTheory.Limits.Cofork f g

full_name: CategoryTheory.Limits.isColimitIdCofork
code: /-- The identity on `Y` is a coequalizer of `(f, g)`, where `f = g`.  -/
def isColimitIdCofork (h : f = g) : IsColimit (idCofork h) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.idCofork h)

full_name: CategoryTheory.Limits.isIso_colimit_cocone_parallelPair_of_eq
code: /-- Every coequalizer of `(f, g)`, where `f = g`, is an isomorphism. -/
theorem isIso_colimit_cocone_parallelPair_of_eq (h₀ : f = g) {c : Cofork f g} (h : IsColimit c) :
    IsIso c.π 
goal: CategoryTheory.IsIso c.π

full_name: CategoryTheory.Limits.coequalizer.π_of_eq
code: /-- The coequalizer of `(f, g)`, where `f = g`, is an isomorphism. -/
theorem coequalizer.π_of_eq [HasCoequalizer f g] (h : f = g) : IsIso (coequalizer.π f g) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.coequalizer.π f g)

full_name: CategoryTheory.Limits.isIso_colimit_cocone_parallelPair_of_self
code: /-- Every coequalizer of `(f, f)` is an isomorphism. -/
theorem isIso_colimit_cocone_parallelPair_of_self {c : Cofork f f} (h : IsColimit c) : IsIso c.π 
goal: CategoryTheory.IsIso c.π

full_name: CategoryTheory.Limits.isIso_limit_cocone_parallelPair_of_epi
code: /-- A coequalizer that is a monomorphism is an isomorphism. -/
theorem isIso_limit_cocone_parallelPair_of_epi {c : Cofork f g} (h : IsColimit c) [Mono c.π] :
    IsIso c.π 
goal: CategoryTheory.IsIso c.π

full_name: CategoryTheory.Limits.eq_of_mono_cofork_π
code: /-- Two morphisms are equal if there is a cofork whose projection is mono. -/
theorem eq_of_mono_cofork_π (t : Cofork f g) [Mono (Cofork.π t)] : f = g 
goal: f = g

full_name: CategoryTheory.Limits.eq_of_mono_coequalizer
code: /-- If the coequalizer of two morphisms is a monomorphism, then the two morphisms are equal. -/
theorem eq_of_mono_coequalizer [HasCoequalizer f g] [Mono (coequalizer.π f g)] : f = g 
goal: f = g

full_name: CategoryTheory.Limits.hasCoequalizer_of_self
code: instance hasCoequalizer_of_self : HasCoequalizer f f 
goal: CategoryTheory.Limits.HasCoequalizer f f

full_name: CategoryTheory.Limits.coequalizer.π_of_self
code: /-- The coequalizer projection for `(f, f)` is an isomorphism. -/
instance coequalizer.π_of_self : IsIso (coequalizer.π f f) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.coequalizer.π f f)

full_name: CategoryTheory.Limits.coequalizer.isoTargetOfSelf
code: /-- The coequalizer of a morphism with itself is isomorphic to the target. -/
noncomputable def coequalizer.isoTargetOfSelf : coequalizer f f ≅ Y 
goal: CategoryTheory.Limits.coequalizer f f ≅ Y

full_name: CategoryTheory.Limits.coequalizer.isoTargetOfSelf_hom
code: @[simp]
theorem coequalizer.isoTargetOfSelf_hom :
    (coequalizer.isoTargetOfSelf f).hom = coequalizer.desc (𝟙 Y) (by simp) 
goal: (CategoryTheory.Limits.coequalizer.isoTargetOfSelf f).hom =
  CategoryTheory.Limits.coequalizer.desc (CategoryTheory.CategoryStruct.id Y) ⋯

full_name: CategoryTheory.Limits.coequalizer.isoTargetOfSelf_inv
code: @[simp]
theorem coequalizer.isoTargetOfSelf_inv : (coequalizer.isoTargetOfSelf f).inv = coequalizer.π f f 
goal: (CategoryTheory.Limits.coequalizer.isoTargetOfSelf f).inv = CategoryTheory.Limits.coequalizer.π f f

full_name: CategoryTheory.Limits.equalizerComparison
code: /-- The comparison morphism for the equalizer of `f,g`.
This is an isomorphism iff `G` preserves the equalizer of `f,g`; see
`CategoryTheory/Limits/Preserves/Shapes/Equalizers.lean`
-/
noncomputable def equalizerComparison [HasEqualizer f g] [HasEqualizer (G.map f) (G.map g)] :
    G.obj (equalizer f g) ⟶ equalizer (G.map f) (G.map g) 
goal: G.obj (CategoryTheory.Limits.equalizer f g) ⟶ CategoryTheory.Limits.equalizer (G.map f) (G.map g)

full_name: CategoryTheory.Limits.equalizerComparison_comp_π
code: @[reassoc (attr := simp)]
theorem equalizerComparison_comp_π [HasEqualizer f g] [HasEqualizer (G.map f) (G.map g)] :
    equalizerComparison f g G ≫ equalizer.ι (G.map f) (G.map g) = G.map (equalizer.ι f g) 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.equalizerComparison f g G)
    (CategoryTheory.Limits.equalizer.ι (G.map f) (G.map g)) =
  G.map (CategoryTheory.Limits.equalizer.ι f g)

full_name: CategoryTheory.Limits.map_lift_equalizerComparison
code: @[reassoc (attr := simp)]
theorem map_lift_equalizerComparison [HasEqualizer f g] [HasEqualizer (G.map f) (G.map g)] {Z : C}
    {h : Z ⟶ X} (w : h ≫ f = h ≫ g) :
    G.map (equalizer.lift h w) ≫ equalizerComparison f g G =
      equalizer.lift (G.map h) (by simp only [← G.map_comp, w]) 
goal: CategoryTheory.CategoryStruct.comp (G.map (CategoryTheory.Limits.equalizer.lift h w))
    (CategoryTheory.Limits.equalizerComparison f g G) =
  CategoryTheory.Limits.equalizer.lift (G.map h) ⋯

full_name: CategoryTheory.Limits.coequalizerComparison
code: /-- The comparison morphism for the coequalizer of `f,g`. -/
noncomputable def coequalizerComparison [HasCoequalizer f g] [HasCoequalizer (G.map f) (G.map g)] :
    coequalizer (G.map f) (G.map g) ⟶ G.obj (coequalizer f g) 
goal: CategoryTheory.Limits.coequalizer (G.map f) (G.map g) ⟶ G.obj (CategoryTheory.Limits.coequalizer f g)

full_name: CategoryTheory.Limits.ι_comp_coequalizerComparison
code: @[reassoc (attr := simp)]
theorem ι_comp_coequalizerComparison [HasCoequalizer f g] [HasCoequalizer (G.map f) (G.map g)] :
    coequalizer.π _ _ ≫ coequalizerComparison f g G = G.map (coequalizer.π _ _) 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.coequalizer.π (G.map f) (G.map g))
    (CategoryTheory.Limits.coequalizerComparison f g G) =
  G.map (CategoryTheory.Limits.coequalizer.π f g)

full_name: CategoryTheory.Limits.coequalizerComparison_map_desc
code: @[reassoc (attr := simp)]
theorem coequalizerComparison_map_desc [HasCoequalizer f g] [HasCoequalizer (G.map f) (G.map g)]
    {Z : C} {h : Y ⟶ Z} (w : f ≫ h = g ≫ h) :
    coequalizerComparison f g G ≫ G.map (coequalizer.desc h w) =
      coequalizer.desc (G.map h) (by simp only [← G.map_comp, w]) 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.coequalizerComparison f g G)
    (G.map (CategoryTheory.Limits.coequalizer.desc h w)) =
  CategoryTheory.Limits.coequalizer.desc (G.map h) ⋯

full_name: CategoryTheory.Limits.HasEqualizers
code: /-- `HasEqualizers` represents a choice of equalizer for every pair of morphisms -/
abbrev HasEqualizers 
goal: Prop

full_name: CategoryTheory.Limits.HasCoequalizers
code: /-- `HasCoequalizers` represents a choice of coequalizer for every pair of morphisms -/
abbrev HasCoequalizers 
goal: Prop

full_name: CategoryTheory.Limits.hasEqualizers_of_hasLimit_parallelPair
code: /-- If `C` has all limits of diagrams `parallelPair f g`, then it has all equalizers -/
theorem hasEqualizers_of_hasLimit_parallelPair
    [∀ {X Y : C} {f g : X ⟶ Y}, HasLimit (parallelPair f g)] : HasEqualizers C 
goal: CategoryTheory.Limits.HasEqualizers C

full_name: CategoryTheory.Limits.hasCoequalizers_of_hasColimit_parallelPair
code: /-- If `C` has all colimits of diagrams `parallelPair f g`, then it has all coequalizers -/
theorem hasCoequalizers_of_hasColimit_parallelPair
    [∀ {X Y : C} {f g : X ⟶ Y}, HasColimit (parallelPair f g)] : HasCoequalizers C 
goal: CategoryTheory.Limits.HasCoequalizers C

full_name: CategoryTheory.Limits.coneOfIsSplitMono_pt
code: /-- A split mono `f` equalizes `(retraction f ≫ f)` and `(𝟙 Y)`.
Here we build the cone, and show in `isSplitMonoEqualizes` that it is a limit cone.
-/
-- @[simps (config := { rhsMd := semireducible })] Porting note: no semireducible
@[simps!]
noncomputable def coneOfIsSplitMono : Fork (𝟙 Y) (retraction f ≫ f) 
goal: (CategoryTheory.Limits.coneOfIsSplitMono f).pt = X

full_name: CategoryTheory.Limits.coneOfIsSplitMono_π_app
code: /-- A split mono `f` equalizes `(retraction f ≫ f)` and `(𝟙 Y)`.
Here we build the cone, and show in `isSplitMonoEqualizes` that it is a limit cone.
-/
-- @[simps (config := { rhsMd := semireducible })] Porting note: no semireducible
@[simps!]
noncomputable def coneOfIsSplitMono : Fork (𝟙 Y) (retraction f ≫ f) 
goal: ∀ (X_1 : CategoryTheory.Limits.WalkingParallelPair),
  (CategoryTheory.Limits.coneOfIsSplitMono f).π.app X_1 =
    CategoryTheory.Limits.WalkingParallelPair.rec (motive := fun t =>
      X_1 = t →
        (X ⟶
          (CategoryTheory.Limits.parallelPair (CategoryTheory.CategoryStruct.id Y)
                (CategoryTheory.CategoryStruct.comp (CategoryTheory.retraction f) f)).obj
            X_1))
      (fun h => ⋯ ▸ f) (fun h => ⋯ ▸ f) X_1 ⋯

full_name: CategoryTheory.Limits.coneOfIsSplitMono
code: /-- A split mono `f` equalizes `(retraction f ≫ f)` and `(𝟙 Y)`.
Here we build the cone, and show in `isSplitMonoEqualizes` that it is a limit cone.
-/
-- @[simps (config := { rhsMd := semireducible })] Porting note: no semireducible
@[simps!]
noncomputable def coneOfIsSplitMono : Fork (𝟙 Y) (retraction f ≫ f) 
goal: CategoryTheory.Limits.Fork (CategoryTheory.CategoryStruct.id Y)
  (CategoryTheory.CategoryStruct.comp (CategoryTheory.retraction f) f)

full_name: CategoryTheory.Limits.coneOfIsSplitMono_ι
code: @[simp]
theorem coneOfIsSplitMono_ι : (coneOfIsSplitMono f).ι = f 
goal: (CategoryTheory.Limits.coneOfIsSplitMono f).ι = f

full_name: CategoryTheory.Limits.isSplitMonoEqualizes
code: /-- A split mono `f` equalizes `(retraction f ≫ f)` and `(𝟙 Y)`.
-/
noncomputable def isSplitMonoEqualizes {X Y : C} (f : X ⟶ Y) [IsSplitMono f] :
    IsLimit (coneOfIsSplitMono f) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.coneOfIsSplitMono f)

full_name: CategoryTheory.Limits.splitMonoOfEqualizer
code: /-- We show that the converse to `isSplitMonoEqualizes` is true:
Whenever `f` equalizes `(r ≫ f)` and `(𝟙 Y)`, then `r` is a retraction of `f`. -/
def splitMonoOfEqualizer {X Y : C} {f : X ⟶ Y} {r : Y ⟶ X} (hr : f ≫ r ≫ f = f)
    (h : IsLimit (Fork.ofι f (hr.trans (Category.comp_id _).symm : f ≫ r ≫ f = f ≫ 𝟙 Y))) :
    SplitMono f 
goal: CategoryTheory.SplitMono f

full_name: CategoryTheory.Limits.isEqualizerCompMono
code: /-- The fork obtained by postcomposing an equalizer fork with a monomorphism is an equalizer. -/
def isEqualizerCompMono {c : Fork f g} (i : IsLimit c) {Z : C} (h : Y ⟶ Z) [hm : Mono h] :
    have : Fork.ι c ≫ f ≫ h = Fork.ι c ≫ g ≫ h := by
      simp only [← Category.assoc]
      exact congrArg (· ≫ h) c.condition
    IsLimit (Fork.ofι c.ι (by simp [this]) : Fork (f ≫ h) (g ≫ h)) 
goal: let_fun this := ⋯;
CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.Fork.ofι c.ι ⋯)

full_name: CategoryTheory.Limits.hasEqualizer_comp_mono
code: @[instance]
theorem hasEqualizer_comp_mono [HasEqualizer f g] {Z : C} (h : Y ⟶ Z) [Mono h] :
    HasEqualizer (f ≫ h) (g ≫ h) 
goal: CategoryTheory.Limits.HasEqualizer (CategoryTheory.CategoryStruct.comp f h) (CategoryTheory.CategoryStruct.comp g h)

full_name: CategoryTheory.Limits.splitMonoOfIdempotentOfIsLimitFork
code: /-- An equalizer of an idempotent morphism and the identity is split mono. -/
@[simps]
def splitMonoOfIdempotentOfIsLimitFork {X : C} {f : X ⟶ X} (hf : f ≫ f = f) {c : Fork (𝟙 X) f}
    (i : IsLimit c) : SplitMono c.ι 
goal: CategoryTheory.SplitMono c.ι

full_name: CategoryTheory.Limits.splitMonoOfIdempotentOfIsLimitFork_retraction
code: /-- An equalizer of an idempotent morphism and the identity is split mono. -/
@[simps]
def splitMonoOfIdempotentOfIsLimitFork {X : C} {f : X ⟶ X} (hf : f ≫ f = f) {c : Fork (𝟙 X) f}
    (i : IsLimit c) : SplitMono c.ι 
goal: (CategoryTheory.Limits.splitMonoOfIdempotentOfIsLimitFork C hf i).retraction =
  i.lift (CategoryTheory.Limits.Fork.ofι f ⋯)

full_name: CategoryTheory.Limits.splitMonoOfIdempotentEqualizer
code: /-- The equalizer of an idempotent morphism and the identity is split mono. -/
noncomputable def splitMonoOfIdempotentEqualizer {X : C} {f : X ⟶ X} (hf : f ≫ f = f)
    [HasEqualizer (𝟙 X) f] : SplitMono (equalizer.ι (𝟙 X) f) 
goal: CategoryTheory.SplitMono (CategoryTheory.Limits.equalizer.ι (CategoryTheory.CategoryStruct.id X) f)

full_name: CategoryTheory.Limits.coconeOfIsSplitEpi
code: /-- A split epi `f` coequalizes `(f ≫ section_ f)` and `(𝟙 X)`.
Here we build the cocone, and show in `isSplitEpiCoequalizes` that it is a colimit cocone.
-/
-- @[simps (config := { rhsMd := semireducible })] Porting note: no semireducible
@[simps!]
noncomputable def coconeOfIsSplitEpi : Cofork (𝟙 X) (f ≫ section_ f) 
goal: CategoryTheory.Limits.Cofork (CategoryTheory.CategoryStruct.id X)
  (CategoryTheory.CategoryStruct.comp f (CategoryTheory.section_ f))

full_name: CategoryTheory.Limits.coconeOfIsSplitEpi_ι_app
code: /-- A split epi `f` coequalizes `(f ≫ section_ f)` and `(𝟙 X)`.
Here we build the cocone, and show in `isSplitEpiCoequalizes` that it is a colimit cocone.
-/
-- @[simps (config := { rhsMd := semireducible })] Porting note: no semireducible
@[simps!]
noncomputable def coconeOfIsSplitEpi : Cofork (𝟙 X) (f ≫ section_ f) 
goal: ∀ (X_1 : CategoryTheory.Limits.WalkingParallelPair),
  (CategoryTheory.Limits.coconeOfIsSplitEpi f).ι.app X_1 = CategoryTheory.Limits.WalkingParallelPair.rec f f X_1

full_name: CategoryTheory.Limits.coconeOfIsSplitEpi_pt
code: /-- A split epi `f` coequalizes `(f ≫ section_ f)` and `(𝟙 X)`.
Here we build the cocone, and show in `isSplitEpiCoequalizes` that it is a colimit cocone.
-/
-- @[simps (config := { rhsMd := semireducible })] Porting note: no semireducible
@[simps!]
noncomputable def coconeOfIsSplitEpi : Cofork (𝟙 X) (f ≫ section_ f) 
goal: (CategoryTheory.Limits.coconeOfIsSplitEpi f).pt = Y

full_name: CategoryTheory.Limits.coconeOfIsSplitEpi_π
code: @[simp]
theorem coconeOfIsSplitEpi_π : (coconeOfIsSplitEpi f).π = f 
goal: (CategoryTheory.Limits.coconeOfIsSplitEpi f).π = f

full_name: CategoryTheory.Limits.isSplitEpiCoequalizes
code: /-- A split epi `f` coequalizes `(f ≫ section_ f)` and `(𝟙 X)`.
-/
noncomputable def isSplitEpiCoequalizes {X Y : C} (f : X ⟶ Y) [IsSplitEpi f] :
    IsColimit (coconeOfIsSplitEpi f) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.coconeOfIsSplitEpi f)

full_name: CategoryTheory.Limits.splitEpiOfCoequalizer
code: /-- We show that the converse to `isSplitEpiEqualizes` is true:
Whenever `f` coequalizes `(f ≫ s)` and `(𝟙 X)`, then `s` is a section of `f`. -/
def splitEpiOfCoequalizer {X Y : C} {f : X ⟶ Y} {s : Y ⟶ X} (hs : f ≫ s ≫ f = f)
    (h :
      IsColimit
        (Cofork.ofπ f
          ((Category.assoc _ _ _).trans <| hs.trans (Category.id_comp f).symm :
            (f ≫ s) ≫ f = 𝟙 X ≫ f))) :
    SplitEpi f 
goal: CategoryTheory.SplitEpi f

full_name: CategoryTheory.Limits.isCoequalizerEpiComp
code: /-- The cofork obtained by precomposing a coequalizer cofork with an epimorphism is
a coequalizer. -/
def isCoequalizerEpiComp {c : Cofork f g} (i : IsColimit c) {W : C} (h : W ⟶ X) [hm : Epi h] :
    have : (h ≫ f) ≫ Cofork.π c = (h ≫ g) ≫ Cofork.π c := by
      simp only [Category.assoc]
      exact congrArg (h ≫ ·) c.condition
    IsColimit (Cofork.ofπ c.π (this) : Cofork (h ≫ f) (h ≫ g)) 
goal: let_fun this := ⋯;
CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.Cofork.ofπ c.π this)

full_name: CategoryTheory.Limits.hasCoequalizer_epi_comp
code: theorem hasCoequalizer_epi_comp [HasCoequalizer f g] {W : C} (h : W ⟶ X) [Epi h] :
    HasCoequalizer (h ≫ f) (h ≫ g) 
goal: CategoryTheory.Limits.HasCoequalizer (CategoryTheory.CategoryStruct.comp h f) (CategoryTheory.CategoryStruct.comp h g)

full_name: CategoryTheory.Limits.splitEpiOfIdempotentOfIsColimitCofork
code: /-- A coequalizer of an idempotent morphism and the identity is split epi. -/
@[simps]
def splitEpiOfIdempotentOfIsColimitCofork {X : C} {f : X ⟶ X} (hf : f ≫ f = f) {c : Cofork (𝟙 X) f}
    (i : IsColimit c) : SplitEpi c.π 
goal: CategoryTheory.SplitEpi c.π

full_name: CategoryTheory.Limits.splitEpiOfIdempotentOfIsColimitCofork_section_
code: /-- A coequalizer of an idempotent morphism and the identity is split epi. -/
@[simps]
def splitEpiOfIdempotentOfIsColimitCofork {X : C} {f : X ⟶ X} (hf : f ≫ f = f) {c : Cofork (𝟙 X) f}
    (i : IsColimit c) : SplitEpi c.π 
goal: (CategoryTheory.Limits.splitEpiOfIdempotentOfIsColimitCofork C hf i).section_ =
  i.desc (CategoryTheory.Limits.Cofork.ofπ f ⋯)

full_name: CategoryTheory.Limits.splitEpiOfIdempotentCoequalizer
code: /-- The coequalizer of an idempotent morphism and the identity is split epi. -/
noncomputable def splitEpiOfIdempotentCoequalizer {X : C} {f : X ⟶ X} (hf : f ≫ f = f)
    [HasCoequalizer (𝟙 X) f] : SplitEpi (coequalizer.π (𝟙 X) f) 
goal: CategoryTheory.SplitEpi (CategoryTheory.Limits.coequalizer.π (CategoryTheory.CategoryStruct.id X) f)