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

full_name: CategoryTheory.Limits.HasKernel
code: /-- A morphism `f` has a kernel if the functor `ParallelPair f 0` has a limit. -/
abbrev HasKernel {X Y : C} (f : X ⟶ Y) : Prop 
goal: Prop

full_name: CategoryTheory.Limits.HasCokernel
code: /-- A morphism `f` has a cokernel if the functor `ParallelPair f 0` has a colimit. -/
abbrev HasCokernel {X Y : C} (f : X ⟶ Y) : Prop 
goal: Prop

full_name: CategoryTheory.Limits.KernelFork
code: /-- A kernel fork is just a fork where the second morphism is a zero morphism. -/
abbrev KernelFork 
goal: Type (max u v)

full_name: CategoryTheory.Limits.KernelFork.condition
code: @[reassoc (attr := simp)]
theorem KernelFork.condition (s : KernelFork f) : Fork.ι s ≫ f = 0 
goal: CategoryTheory.Limits.Fork.ι s ≫ f = 0

full_name: CategoryTheory.Limits.KernelFork.app_one
code: theorem KernelFork.app_one (s : KernelFork f) : s.π.app one = 0 
goal: s.π.app CategoryTheory.Limits.WalkingParallelPair.one = 0

full_name: CategoryTheory.Limits.KernelFork.ofι
code: /-- A morphism `ι` satisfying `ι ≫ f = 0` determines a kernel fork over `f`. -/
abbrev KernelFork.ofι {Z : C} (ι : Z ⟶ X) (w : ι ≫ f = 0) : KernelFork f 
goal: CategoryTheory.Limits.KernelFork f

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

full_name: CategoryTheory.Limits.isoOfι
code: /-- Every kernel fork `s` is isomorphic (actually, equal) to `fork.ofι (fork.ι s) _`. -/
def isoOfι (s : Fork f 0) : s ≅ Fork.ofι (Fork.ι s) (Fork.condition s) 
goal: s ≅ CategoryTheory.Limits.Fork.ofι s.ι ⋯

full_name: CategoryTheory.Limits.ofιCongr
code: /-- If `ι = ι'`, then `fork.ofι ι _` and `fork.ofι ι' _` are isomorphic. -/
def ofιCongr {P : C} {ι ι' : P ⟶ X} {w : ι ≫ f = 0} (h : ι = ι') :
    KernelFork.ofι ι w ≅ KernelFork.ofι ι' (by rw [← h, w]) 
goal: CategoryTheory.Limits.KernelFork.ofι ι w ≅ CategoryTheory.Limits.KernelFork.ofι ι' ⋯

full_name: CategoryTheory.Limits.compNatIso
code: /-- If `F` is an equivalence, then applying `F` to a diagram indexing a (co)kernel of `f` yields
    the diagram indexing the (co)kernel of `F.map f`. -/
def compNatIso {D : Type u'} [Category.{v} D] [HasZeroMorphisms D] (F : C ⥤ D) [F.IsEquivalence] :
    parallelPair f 0 ⋙ F ≅ parallelPair (F.map f) 0 
goal: CategoryTheory.Limits.parallelPair f 0 ⋙ F ≅ CategoryTheory.Limits.parallelPair (F.map f) 0

full_name: CategoryTheory.Limits.KernelFork.IsLimit.lift'
code: /-- If `s` is a limit kernel fork and `k : W ⟶ X` satisfies `k ≫ f = 0`, then there is some
    `l : W ⟶ s.X` such that `l ≫ fork.ι s = k`. -/
def KernelFork.IsLimit.lift' {s : KernelFork f} (hs : IsLimit s) {W : C} (k : W ⟶ X)
    (h : k ≫ f = 0) : { l : W ⟶ s.pt // l ≫ Fork.ι s = k } 
goal: { l // l ≫ CategoryTheory.Limits.Fork.ι s = k }

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

full_name: CategoryTheory.Limits.KernelFork.IsLimit.ofι
code: /-- This is a more convenient formulation to show that a `KernelFork` constructed using
`KernelFork.ofι` is a limit cone.
-/
def KernelFork.IsLimit.ofι {W : C} (g : W ⟶ X) (eq : g ≫ f = 0)
    (lift : ∀ {W' : C} (g' : W' ⟶ X) (_ : g' ≫ f = 0), W' ⟶ W)
    (fac : ∀ {W' : C} (g' : W' ⟶ X) (eq' : g' ≫ f = 0), lift g' eq' ≫ g = g')
    (uniq :
      ∀ {W' : C} (g' : W' ⟶ X) (eq' : g' ≫ f = 0) (m : W' ⟶ W) (_ : m ≫ g = g'), m = lift g' eq') :
    IsLimit (KernelFork.ofι g eq) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι g eq)

full_name: CategoryTheory.Limits.KernelFork.IsLimit.ofι'
code: /-- This is a more convenient formulation to show that a `KernelFork` of the form
`KernelFork.ofι i _` is a limit cone when we know that `i` is a monomorphism. -/
def KernelFork.IsLimit.ofι' {X Y K : C} {f : X ⟶ Y} (i : K ⟶ X) (w : i ≫ f = 0)
    (h : ∀ {A : C} (k : A ⟶ X) (_ : k ≫ f = 0), { l : A ⟶ K // l ≫ i = k}) [hi : Mono i] :
    IsLimit (KernelFork.ofι i w) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι i w)

full_name: CategoryTheory.Limits.isKernelCompMono
code: /-- Every kernel of `f` induces a kernel of `f ≫ g` if `g` is mono. -/
def isKernelCompMono {c : KernelFork f} (i : IsLimit c) {Z} (g : Y ⟶ Z) [hg : Mono g] {h : X ⟶ Z}
    (hh : h = f ≫ g) : IsLimit (KernelFork.ofι c.ι (by simp [hh]) : KernelFork h) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι (CategoryTheory.Limits.Fork.ι c) ⋯)

full_name: CategoryTheory.Limits.isKernelCompMono_lift
code: theorem isKernelCompMono_lift {c : KernelFork f} (i : IsLimit c) {Z} (g : Y ⟶ Z) [hg : Mono g]
    {h : X ⟶ Z} (hh : h = f ≫ g) (s : KernelFork h) :
    (isKernelCompMono i g hh).lift s = i.lift (Fork.ofι s.ι (by
      rw [← cancel_mono g, Category.assoc, ← hh]
      simp)) 
goal: (CategoryTheory.Limits.isKernelCompMono i g hh).lift s =
  i.lift (CategoryTheory.Limits.Fork.ofι (CategoryTheory.Limits.Fork.ι s) ⋯)

full_name: CategoryTheory.Limits.isKernelOfComp
code: /-- Every kernel of `f ≫ g` is also a kernel of `f`, as long as `c.ι ≫ f` vanishes. -/
def isKernelOfComp {W : C} (g : Y ⟶ W) (h : X ⟶ W) {c : KernelFork h} (i : IsLimit c)
    (hf : c.ι ≫ f = 0) (hfg : f ≫ g = h) : IsLimit (KernelFork.ofι c.ι hf) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι (CategoryTheory.Limits.Fork.ι c) hf)

full_name: CategoryTheory.Limits.KernelFork.IsLimit.ofId
code: /-- `X` identifies to the kernel of a zero map `X ⟶ Y`. -/
def KernelFork.IsLimit.ofId {X Y : C} (f : X ⟶ Y) (hf : f = 0) :
    IsLimit (KernelFork.ofι (𝟙 X) (show 𝟙 X ≫ f = 0 by rw [hf, comp_zero])) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι (𝟙 X) ⋯)

full_name: CategoryTheory.Limits.KernelFork.IsLimit.ofMonoOfIsZero
code: /-- Any zero object identifies to the kernel of a given monomorphisms. -/
def KernelFork.IsLimit.ofMonoOfIsZero {X Y : C} {f : X ⟶ Y} (c : KernelFork f)
    (hf : Mono f) (h : IsZero c.pt) : IsLimit c 
goal: CategoryTheory.Limits.IsLimit c

full_name: CategoryTheory.Limits.KernelFork.IsLimit.isIso_ι
code: lemma KernelFork.IsLimit.isIso_ι {X Y : C} {f : X ⟶ Y} (c : KernelFork f)
    (hc : IsLimit c) (hf : f = 0) : IsIso c.ι 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.Fork.ι c)

full_name: CategoryTheory.Limits.KernelFork.mapOfIsLimit
code: /-- The morphism between points of kernel forks induced by a morphism
in the category of arrows. -/
def mapOfIsLimit (kf : KernelFork f) {kf' : KernelFork f'} (hf' : IsLimit kf')
    (φ : Arrow.mk f ⟶ Arrow.mk f') : kf.pt ⟶ kf'.pt 
goal: kf.pt ⟶ kf'.pt

full_name: CategoryTheory.Limits.KernelFork.mapOfIsLimit_ι
code: @[reassoc (attr := simp)]
lemma mapOfIsLimit_ι (kf : KernelFork f) {kf' : KernelFork f'} (hf' : IsLimit kf')
    (φ : Arrow.mk f ⟶ Arrow.mk f') :
    kf.mapOfIsLimit hf' φ ≫ kf'.ι = kf.ι ≫ φ.left 
goal: kf.mapOfIsLimit hf' φ ≫ CategoryTheory.Limits.Fork.ι kf' = CategoryTheory.Limits.Fork.ι kf ≫ φ.left

full_name: CategoryTheory.Limits.KernelFork.mapIsoOfIsLimit_inv
code: /-- The isomorphism between points of limit kernel forks induced by an isomorphism
in the category of arrows. -/
@[simps]
def mapIsoOfIsLimit {kf : KernelFork f} {kf' : KernelFork f'}
    (hf : IsLimit kf) (hf' : IsLimit kf')
    (φ : Arrow.mk f ≅ Arrow.mk f') : kf.pt ≅ kf'.pt 
goal: (CategoryTheory.Limits.KernelFork.mapIsoOfIsLimit hf hf' φ).inv = kf'.mapOfIsLimit hf φ.inv

full_name: CategoryTheory.Limits.KernelFork.mapIsoOfIsLimit
code: /-- The isomorphism between points of limit kernel forks induced by an isomorphism
in the category of arrows. -/
@[simps]
def mapIsoOfIsLimit {kf : KernelFork f} {kf' : KernelFork f'}
    (hf : IsLimit kf) (hf' : IsLimit kf')
    (φ : Arrow.mk f ≅ Arrow.mk f') : kf.pt ≅ kf'.pt 
goal: kf.pt ≅ kf'.pt

full_name: CategoryTheory.Limits.KernelFork.mapIsoOfIsLimit_hom
code: /-- The isomorphism between points of limit kernel forks induced by an isomorphism
in the category of arrows. -/
@[simps]
def mapIsoOfIsLimit {kf : KernelFork f} {kf' : KernelFork f'}
    (hf : IsLimit kf) (hf' : IsLimit kf')
    (φ : Arrow.mk f ≅ Arrow.mk f') : kf.pt ≅ kf'.pt 
goal: (CategoryTheory.Limits.KernelFork.mapIsoOfIsLimit hf hf' φ).hom = kf.mapOfIsLimit hf' φ.hom

full_name: CategoryTheory.Limits.kernel
code: /-- The kernel of a morphism, expressed as the equalizer with the 0 morphism. -/
abbrev kernel (f : X ⟶ Y) [HasKernel f] : C 
goal: C

full_name: CategoryTheory.Limits.kernel.ι
code: /-- The map from `kernel f` into the source of `f`. -/
abbrev kernel.ι : kernel f ⟶ X 
goal: CategoryTheory.Limits.kernel f ⟶ X

full_name: CategoryTheory.Limits.equalizer_as_kernel
code: @[simp]
theorem equalizer_as_kernel : equalizer.ι f 0 = kernel.ι f 
goal: CategoryTheory.Limits.equalizer.ι f 0 = CategoryTheory.Limits.kernel.ι f

full_name: CategoryTheory.Limits.kernel.condition
code: @[reassoc (attr := simp)]
theorem kernel.condition : kernel.ι f ≫ f = 0 
goal: CategoryTheory.Limits.kernel.ι f ≫ f = 0

full_name: CategoryTheory.Limits.kernelIsKernel
code: /-- The kernel built from `kernel.ι f` is limiting. -/
def kernelIsKernel : IsLimit (Fork.ofι (kernel.ι f) ((kernel.condition f).trans comp_zero.symm)) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.Fork.ofι (CategoryTheory.Limits.kernel.ι f) ⋯)

full_name: CategoryTheory.Limits.kernel.lift
code: /-- Given any morphism `k : W ⟶ X` satisfying `k ≫ f = 0`, `k` factors through `kernel.ι f`
    via `kernel.lift : W ⟶ kernel f`. -/
abbrev kernel.lift {W : C} (k : W ⟶ X) (h : k ≫ f = 0) : W ⟶ kernel f 
goal: W ⟶ CategoryTheory.Limits.kernel f

full_name: CategoryTheory.Limits.kernel.lift_ι
code: @[reassoc (attr := simp)]
theorem kernel.lift_ι {W : C} (k : W ⟶ X) (h : k ≫ f = 0) : kernel.lift f k h ≫ kernel.ι f = k 
goal: CategoryTheory.Limits.kernel.lift f k h ≫ CategoryTheory.Limits.kernel.ι f = k

full_name: CategoryTheory.Limits.kernel.lift_zero
code: @[simp]
theorem kernel.lift_zero {W : C} {h} : kernel.lift f (0 : W ⟶ X) h = 0 
goal: CategoryTheory.Limits.kernel.lift f 0 h = 0

full_name: CategoryTheory.Limits.kernel.lift_mono
code: instance kernel.lift_mono {W : C} (k : W ⟶ X) (h : k ≫ f = 0) [Mono k] : Mono (kernel.lift f k h) 
goal: CategoryTheory.Mono (CategoryTheory.Limits.kernel.lift f k h)

full_name: CategoryTheory.Limits.kernel.lift'
code: /-- Any morphism `k : W ⟶ X` satisfying `k ≫ f = 0` induces a morphism `l : W ⟶ kernel f` such that
    `l ≫ kernel.ι f = k`. -/
def kernel.lift' {W : C} (k : W ⟶ X) (h : k ≫ f = 0) : { l : W ⟶ kernel f // l ≫ kernel.ι f = k } 
goal: { l // l ≫ CategoryTheory.Limits.kernel.ι f = k }

full_name: CategoryTheory.Limits.kernel.map
code: /-- A commuting square induces a morphism of kernels. -/
abbrev kernel.map {X' Y' : C} (f' : X' ⟶ Y') [HasKernel f'] (p : X ⟶ X') (q : Y ⟶ Y')
    (w : f ≫ q = p ≫ f') : kernel f ⟶ kernel f' 
goal: CategoryTheory.Limits.kernel f ⟶ CategoryTheory.Limits.kernel f'

full_name: CategoryTheory.Limits.kernel.lift_map
code: /-- Given a commutative diagram
    X --f--> Y --g--> Z
    |        |        |
    |        |        |
    v        v        v
    X' -f'-> Y' -g'-> Z'
with horizontal arrows composing to zero,
then we obtain a commutative square
   X ---> kernel g
   |         |
   |         | kernel.map
   |         |
   v         v
   X' --> kernel g'
-/
theorem kernel.lift_map {X Y Z X' Y' Z' : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasKernel g] (w : f ≫ g = 0)
    (f' : X' ⟶ Y') (g' : Y' ⟶ Z') [HasKernel g'] (w' : f' ≫ g' = 0) (p : X ⟶ X') (q : Y ⟶ Y')
    (r : Z ⟶ Z') (h₁ : f ≫ q = p ≫ f') (h₂ : g ≫ r = q ≫ g') :
    kernel.lift g f w ≫ kernel.map g g' q r h₂ = p ≫ kernel.lift g' f' w' 
goal: CategoryTheory.Limits.kernel.lift g f w ≫ CategoryTheory.Limits.kernel.map g g' q r h₂ =
  p ≫ CategoryTheory.Limits.kernel.lift g' f' w'

full_name: CategoryTheory.Limits.kernel.mapIso_inv
code: /-- A commuting square of isomorphisms induces an isomorphism of kernels. -/
@[simps]
def kernel.mapIso {X' Y' : C} (f' : X' ⟶ Y') [HasKernel f'] (p : X ≅ X') (q : Y ≅ Y')
    (w : f ≫ q.hom = p.hom ≫ f') : kernel f ≅ kernel f' 
goal: (CategoryTheory.Limits.kernel.mapIso f f' p q w).inv = CategoryTheory.Limits.kernel.map f' f p.inv q.inv ⋯

full_name: CategoryTheory.Limits.kernel.mapIso_hom
code: /-- A commuting square of isomorphisms induces an isomorphism of kernels. -/
@[simps]
def kernel.mapIso {X' Y' : C} (f' : X' ⟶ Y') [HasKernel f'] (p : X ≅ X') (q : Y ≅ Y')
    (w : f ≫ q.hom = p.hom ≫ f') : kernel f ≅ kernel f' 
goal: (CategoryTheory.Limits.kernel.mapIso f f' p q w).hom = CategoryTheory.Limits.kernel.map f f' p.hom q.hom w

full_name: CategoryTheory.Limits.kernel.mapIso
code: /-- A commuting square of isomorphisms induces an isomorphism of kernels. -/
@[simps]
def kernel.mapIso {X' Y' : C} (f' : X' ⟶ Y') [HasKernel f'] (p : X ≅ X') (q : Y ≅ Y')
    (w : f ≫ q.hom = p.hom ≫ f') : kernel f ≅ kernel f' 
goal: CategoryTheory.Limits.kernel f ≅ CategoryTheory.Limits.kernel f'

full_name: CategoryTheory.Limits.kernel.ι_zero_isIso
code: /-- Every kernel of the zero morphism is an isomorphism -/
instance kernel.ι_zero_isIso : IsIso (kernel.ι (0 : X ⟶ Y)) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.kernel.ι 0)

full_name: CategoryTheory.Limits.eq_zero_of_epi_kernel
code: theorem eq_zero_of_epi_kernel [Epi (kernel.ι f)] : f = 0 
goal: f = 0

full_name: CategoryTheory.Limits.kernelZeroIsoSource
code: /-- The kernel of a zero morphism is isomorphic to the source. -/
def kernelZeroIsoSource : kernel (0 : X ⟶ Y) ≅ X 
goal: CategoryTheory.Limits.kernel 0 ≅ X

full_name: CategoryTheory.Limits.kernelZeroIsoSource_hom
code: @[simp]
theorem kernelZeroIsoSource_hom : kernelZeroIsoSource.hom = kernel.ι (0 : X ⟶ Y) 
goal: CategoryTheory.Limits.kernelZeroIsoSource.hom = CategoryTheory.Limits.kernel.ι 0

full_name: CategoryTheory.Limits.kernelZeroIsoSource_inv
code: @[simp]
theorem kernelZeroIsoSource_inv :
    kernelZeroIsoSource.inv = kernel.lift (0 : X ⟶ Y) (𝟙 X) (by simp) 
goal: CategoryTheory.Limits.kernelZeroIsoSource.inv = CategoryTheory.Limits.kernel.lift 0 (𝟙 X) ⋯

full_name: CategoryTheory.Limits.kernelIsoOfEq
code: /-- If two morphisms are known to be equal, then their kernels are isomorphic. -/
def kernelIsoOfEq {f g : X ⟶ Y} [HasKernel f] [HasKernel g] (h : f = g) : kernel f ≅ kernel g 
goal: CategoryTheory.Limits.kernel f ≅ CategoryTheory.Limits.kernel g

full_name: CategoryTheory.Limits.kernelIsoOfEq_refl
code: @[simp]
theorem kernelIsoOfEq_refl {h : f = f} : kernelIsoOfEq h = Iso.refl (kernel f) 
goal: CategoryTheory.Limits.kernelIsoOfEq h = CategoryTheory.Iso.refl (CategoryTheory.Limits.kernel f)

full_name: CategoryTheory.Limits.kernelIsoOfEq_hom_comp_ι
code: @[reassoc (attr := simp)]
theorem kernelIsoOfEq_hom_comp_ι {f g : X ⟶ Y} [HasKernel f] [HasKernel g] (h : f = g) :
    (kernelIsoOfEq h).hom ≫ kernel.ι g = kernel.ι f 
goal: (CategoryTheory.Limits.kernelIsoOfEq h).hom ≫ CategoryTheory.Limits.kernel.ι g = CategoryTheory.Limits.kernel.ι f

full_name: CategoryTheory.Limits.kernelIsoOfEq_inv_comp_ι
code: @[reassoc (attr := simp)]
theorem kernelIsoOfEq_inv_comp_ι {f g : X ⟶ Y} [HasKernel f] [HasKernel g] (h : f = g) :
    (kernelIsoOfEq h).inv ≫ kernel.ι _ = kernel.ι _ 
goal: (CategoryTheory.Limits.kernelIsoOfEq h).inv ≫ CategoryTheory.Limits.kernel.ι f = CategoryTheory.Limits.kernel.ι g

full_name: CategoryTheory.Limits.lift_comp_kernelIsoOfEq_hom
code: @[reassoc (attr := simp)]
theorem lift_comp_kernelIsoOfEq_hom {Z} {f g : X ⟶ Y} [HasKernel f] [HasKernel g] (h : f = g)
    (e : Z ⟶ X) (he) :
    kernel.lift _ e he ≫ (kernelIsoOfEq h).hom = kernel.lift _ e (by simp [← h, he]) 
goal: CategoryTheory.Limits.kernel.lift f e he ≫ (CategoryTheory.Limits.kernelIsoOfEq h).hom =
  CategoryTheory.Limits.kernel.lift g e ⋯

full_name: CategoryTheory.Limits.lift_comp_kernelIsoOfEq_inv
code: @[reassoc (attr := simp)]
theorem lift_comp_kernelIsoOfEq_inv {Z} {f g : X ⟶ Y} [HasKernel f] [HasKernel g] (h : f = g)
    (e : Z ⟶ X) (he) :
    kernel.lift _ e he ≫ (kernelIsoOfEq h).inv = kernel.lift _ e (by simp [h, he]) 
goal: CategoryTheory.Limits.kernel.lift g e he ≫ (CategoryTheory.Limits.kernelIsoOfEq h).inv =
  CategoryTheory.Limits.kernel.lift f e ⋯

full_name: CategoryTheory.Limits.kernelIsoOfEq_trans
code: @[simp]
theorem kernelIsoOfEq_trans {f g h : X ⟶ Y} [HasKernel f] [HasKernel g] [HasKernel h] (w₁ : f = g)
    (w₂ : g = h) : kernelIsoOfEq w₁ ≪≫ kernelIsoOfEq w₂ = kernelIsoOfEq (w₁.trans w₂) 
goal: CategoryTheory.Limits.kernelIsoOfEq w₁ ≪≫ CategoryTheory.Limits.kernelIsoOfEq w₂ = CategoryTheory.Limits.kernelIsoOfEq ⋯

full_name: CategoryTheory.Limits.kernel_not_epi_of_nonzero
code: theorem kernel_not_epi_of_nonzero (w : f ≠ 0) : ¬Epi (kernel.ι f) 
goal: ¬CategoryTheory.Epi (CategoryTheory.Limits.kernel.ι f)

full_name: CategoryTheory.Limits.kernel_not_iso_of_nonzero
code: theorem kernel_not_iso_of_nonzero (w : f ≠ 0) : IsIso (kernel.ι f) → False 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.kernel.ι f) → False

full_name: CategoryTheory.Limits.hasKernel_comp_mono
code: instance hasKernel_comp_mono {X Y Z : C} (f : X ⟶ Y) [HasKernel f] (g : Y ⟶ Z) [Mono g] :
    HasKernel (f ≫ g) 
goal: CategoryTheory.Limits.HasKernel (f ≫ g)

full_name: CategoryTheory.Limits.kernelCompMono_hom
code: /-- When `g` is a monomorphism, the kernel of `f ≫ g` is isomorphic to the kernel of `f`.
-/
@[simps]
def kernelCompMono {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasKernel f] [Mono g] :
    kernel (f ≫ g) ≅ kernel f 
goal: (CategoryTheory.Limits.kernelCompMono f g).hom =
  CategoryTheory.Limits.kernel.lift f (CategoryTheory.Limits.kernel.ι (f ≫ g)) ⋯

full_name: CategoryTheory.Limits.kernelCompMono_inv
code: /-- When `g` is a monomorphism, the kernel of `f ≫ g` is isomorphic to the kernel of `f`.
-/
@[simps]
def kernelCompMono {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasKernel f] [Mono g] :
    kernel (f ≫ g) ≅ kernel f 
goal: (CategoryTheory.Limits.kernelCompMono f g).inv =
  CategoryTheory.Limits.kernel.lift (f ≫ g) (CategoryTheory.Limits.kernel.ι f) ⋯

full_name: CategoryTheory.Limits.kernelCompMono
code: /-- When `g` is a monomorphism, the kernel of `f ≫ g` is isomorphic to the kernel of `f`.
-/
@[simps]
def kernelCompMono {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasKernel f] [Mono g] :
    kernel (f ≫ g) ≅ kernel f 
goal: CategoryTheory.Limits.kernel (f ≫ g) ≅ CategoryTheory.Limits.kernel f

full_name: CategoryTheory.Limits.hasKernel_iso_comp
code: instance hasKernel_iso_comp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso f] [HasKernel g] :
    HasKernel (f ≫ g) 
goal: CategoryTheory.Limits.HasKernel (f ≫ g)

full_name: CategoryTheory.Limits.kernelIsIsoComp_hom
code: /-- When `f` is an isomorphism, the kernel of `f ≫ g` is isomorphic to the kernel of `g`.
-/
@[simps]
def kernelIsIsoComp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso f] [HasKernel g] :
    kernel (f ≫ g) ≅ kernel g 
goal: (CategoryTheory.Limits.kernelIsIsoComp f g).hom =
  CategoryTheory.Limits.kernel.lift g (CategoryTheory.Limits.kernel.ι (f ≫ g) ≫ f) ⋯

full_name: CategoryTheory.Limits.kernelIsIsoComp_inv
code: /-- When `f` is an isomorphism, the kernel of `f ≫ g` is isomorphic to the kernel of `g`.
-/
@[simps]
def kernelIsIsoComp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso f] [HasKernel g] :
    kernel (f ≫ g) ≅ kernel g 
goal: (CategoryTheory.Limits.kernelIsIsoComp f g).inv =
  CategoryTheory.Limits.kernel.lift (f ≫ g) (CategoryTheory.Limits.kernel.ι g ≫ CategoryTheory.inv f) ⋯

full_name: CategoryTheory.Limits.kernelIsIsoComp
code: /-- When `f` is an isomorphism, the kernel of `f ≫ g` is isomorphic to the kernel of `g`.
-/
@[simps]
def kernelIsIsoComp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso f] [HasKernel g] :
    kernel (f ≫ g) ≅ kernel g 
goal: CategoryTheory.Limits.kernel (f ≫ g) ≅ CategoryTheory.Limits.kernel g

full_name: CategoryTheory.Limits.kernel.zeroKernelFork
code: /-- The morphism from the zero object determines a cone on a kernel diagram -/
def kernel.zeroKernelFork : KernelFork f 
goal: CategoryTheory.Limits.KernelFork f

full_name: CategoryTheory.Limits.kernel.isLimitConeZeroCone
code: /-- The map from the zero object is a kernel of a monomorphism -/
def kernel.isLimitConeZeroCone [Mono f] : IsLimit (kernel.zeroKernelFork f) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.kernel.zeroKernelFork f)

full_name: CategoryTheory.Limits.kernel.ofMono
code: /-- The kernel of a monomorphism is isomorphic to the zero object -/
def kernel.ofMono [HasKernel f] [Mono f] : kernel f ≅ 0 
goal: CategoryTheory.Limits.kernel f ≅ 0

full_name: CategoryTheory.Limits.kernel.ι_of_mono
code: /-- The kernel morphism of a monomorphism is a zero morphism -/
theorem kernel.ι_of_mono [HasKernel f] [Mono f] : kernel.ι f = 0 
goal: CategoryTheory.Limits.kernel.ι f = 0

full_name: CategoryTheory.Limits.zeroKernelOfCancelZero
code: /-- If `g ≫ f = 0` implies `g = 0` for all `g`, then `0 : 0 ⟶ X` is a kernel of `f`. -/
def zeroKernelOfCancelZero {X Y : C} (f : X ⟶ Y)
    (hf : ∀ (Z : C) (g : Z ⟶ X) (_ : g ≫ f = 0), g = 0) :
    IsLimit (KernelFork.ofι (0 : 0 ⟶ X) (show 0 ≫ f = 0 by simp)) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι 0 ⋯)

full_name: CategoryTheory.Limits.IsKernel.ofCompIso
code: /-- If `i` is an isomorphism such that `l ≫ i.hom = f`, any kernel of `f` is a kernel of `l`. -/
def IsKernel.ofCompIso {Z : C} (l : X ⟶ Z) (i : Z ≅ Y) (h : l ≫ i.hom = f) {s : KernelFork f}
    (hs : IsLimit s) :
    IsLimit
      (KernelFork.ofι (Fork.ι s) <| show Fork.ι s ≫ l = 0 by simp [← i.comp_inv_eq.2 h.symm]) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι (CategoryTheory.Limits.Fork.ι s) ⋯)

full_name: CategoryTheory.Limits.kernel.ofCompIso
code: /-- If `i` is an isomorphism such that `l ≫ i.hom = f`, the kernel of `f` is a kernel of `l`. -/
def kernel.ofCompIso [HasKernel f] {Z : C} (l : X ⟶ Z) (i : Z ≅ Y) (h : l ≫ i.hom = f) :
    IsLimit
      (KernelFork.ofι (kernel.ι f) <| show kernel.ι f ≫ l = 0 by simp [← i.comp_inv_eq.2 h.symm]) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι (CategoryTheory.Limits.kernel.ι f) ⋯)

full_name: CategoryTheory.Limits.IsKernel.isoKernel
code: /-- If `s` is any limit kernel cone over `f` and if `i` is an isomorphism such that
    `i.hom ≫ s.ι = l`, then `l` is a kernel of `f`. -/
def IsKernel.isoKernel {Z : C} (l : Z ⟶ X) {s : KernelFork f} (hs : IsLimit s) (i : Z ≅ s.pt)
    (h : i.hom ≫ Fork.ι s = l) : IsLimit (KernelFork.ofι l <| show l ≫ f = 0 by simp [← h]) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι l ⋯)

full_name: CategoryTheory.Limits.kernel.isoKernel
code: /-- If `i` is an isomorphism such that `i.hom ≫ kernel.ι f = l`, then `l` is a kernel of `f`. -/
def kernel.isoKernel [HasKernel f] {Z : C} (l : Z ⟶ X) (i : Z ≅ kernel f)
    (h : i.hom ≫ kernel.ι f = l) :
    IsLimit (@KernelFork.ofι _ _ _ _ _ f _ l <| by simp [← h]) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.KernelFork.ofι l ⋯)

full_name: CategoryTheory.Limits.kernel.ι_of_zero
code: /-- The kernel morphism of a zero morphism is an isomorphism -/
theorem kernel.ι_of_zero : IsIso (kernel.ι (0 : X ⟶ Y)) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.kernel.ι 0)

full_name: CategoryTheory.Limits.CokernelCofork
code: /-- A cokernel cofork is just a cofork where the second morphism is a zero morphism. -/
abbrev CokernelCofork 
goal: Type (max u v)

full_name: CategoryTheory.Limits.CokernelCofork.condition
code: @[reassoc (attr := simp)]
theorem CokernelCofork.condition (s : CokernelCofork f) : f ≫ s.π = 0 
goal: f ≫ CategoryTheory.Limits.Cofork.π s = 0

full_name: CategoryTheory.Limits.CokernelCofork.π_eq_zero
code: theorem CokernelCofork.π_eq_zero (s : CokernelCofork f) : s.ι.app zero = 0 
goal: s.ι.app CategoryTheory.Limits.WalkingParallelPair.zero = 0

full_name: CategoryTheory.Limits.CokernelCofork.ofπ
code: /-- A morphism `π` satisfying `f ≫ π = 0` determines a cokernel cofork on `f`. -/
abbrev CokernelCofork.ofπ {Z : C} (π : Y ⟶ Z) (w : f ≫ π = 0) : CokernelCofork f 
goal: CategoryTheory.Limits.CokernelCofork f

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

full_name: CategoryTheory.Limits.isoOfπ
code: /-- Every cokernel cofork `s` is isomorphic (actually, equal) to `cofork.ofπ (cofork.π s) _`. -/
def isoOfπ (s : Cofork f 0) : s ≅ Cofork.ofπ (Cofork.π s) (Cofork.condition s) 
goal: s ≅ CategoryTheory.Limits.Cofork.ofπ s.π ⋯

full_name: CategoryTheory.Limits.ofπCongr
code: /-- If `π = π'`, then `CokernelCofork.of_π π _` and `CokernelCofork.of_π π' _` are isomorphic. -/
def ofπCongr {P : C} {π π' : Y ⟶ P} {w : f ≫ π = 0} (h : π = π') :
    CokernelCofork.ofπ π w ≅ CokernelCofork.ofπ π' (by rw [← h, w]) 
goal: CategoryTheory.Limits.CokernelCofork.ofπ π w ≅ CategoryTheory.Limits.CokernelCofork.ofπ π' ⋯

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

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

full_name: CategoryTheory.Limits.CokernelCofork.IsColimit.ofπ
code: /-- This is a more convenient formulation to show that a `CokernelCofork` constructed using
`CokernelCofork.ofπ` is a limit cone.
-/
def CokernelCofork.IsColimit.ofπ {Z : C} (g : Y ⟶ Z) (eq : f ≫ g = 0)
    (desc : ∀ {Z' : C} (g' : Y ⟶ Z') (_ : f ≫ g' = 0), Z ⟶ Z')
    (fac : ∀ {Z' : C} (g' : Y ⟶ Z') (eq' : f ≫ g' = 0), g ≫ desc g' eq' = g')
    (uniq :
      ∀ {Z' : C} (g' : Y ⟶ Z') (eq' : f ≫ g' = 0) (m : Z ⟶ Z') (_ : g ≫ m = g'), m = desc g' eq') :
    IsColimit (CokernelCofork.ofπ g eq) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ g eq)

full_name: CategoryTheory.Limits.CokernelCofork.IsColimit.ofπ'
code: /-- This is a more convenient formulation to show that a `CokernelCofork` of the form
`CokernelCofork.ofπ p _` is a colimit cocone when we know that `p` is an epimorphism. -/
def CokernelCofork.IsColimit.ofπ' {X Y Q : C} {f : X ⟶ Y} (p : Y ⟶ Q) (w : f ≫ p = 0)
    (h : ∀ {A : C} (k : Y ⟶ A) (_ : f ≫ k = 0), { l : Q ⟶ A // p ≫ l = k}) [hp : Epi p] :
    IsColimit (CokernelCofork.ofπ p w) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ p w)

full_name: CategoryTheory.Limits.isCokernelEpiComp
code: /-- Every cokernel of `f` induces a cokernel of `g ≫ f` if `g` is epi. -/
def isCokernelEpiComp {c : CokernelCofork f} (i : IsColimit c) {W} (g : W ⟶ X) [hg : Epi g]
    {h : W ⟶ Y} (hh : h = g ≫ f) :
    IsColimit (CokernelCofork.ofπ c.π (by rw [hh]; simp) : CokernelCofork h) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ (CategoryTheory.Limits.Cofork.π c) ⋯)

full_name: CategoryTheory.Limits.isCokernelEpiComp_desc
code: @[simp]
theorem isCokernelEpiComp_desc {c : CokernelCofork f} (i : IsColimit c) {W} (g : W ⟶ X) [hg : Epi g]
    {h : W ⟶ Y} (hh : h = g ≫ f) (s : CokernelCofork h) :
    (isCokernelEpiComp i g hh).desc s =
      i.desc
        (Cofork.ofπ s.π
          (by
            rw [← cancel_epi g, ← Category.assoc, ← hh]
            simp)) 
goal: (CategoryTheory.Limits.isCokernelEpiComp i g hh).desc s =
  i.desc (CategoryTheory.Limits.Cofork.ofπ (CategoryTheory.Limits.Cofork.π s) ⋯)

full_name: CategoryTheory.Limits.isCokernelOfComp
code: /-- Every cokernel of `g ≫ f` is also a cokernel of `f`, as long as `f ≫ c.π` vanishes. -/
def isCokernelOfComp {W : C} (g : W ⟶ X) (h : W ⟶ Y) {c : CokernelCofork h} (i : IsColimit c)
    (hf : f ≫ c.π = 0) (hfg : g ≫ f = h) : IsColimit (CokernelCofork.ofπ c.π hf) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ (CategoryTheory.Limits.Cofork.π c) hf)

full_name: CategoryTheory.Limits.CokernelCofork.IsColimit.ofId
code: /-- `Y` identifies to the cokernel of a zero map `X ⟶ Y`. -/
def CokernelCofork.IsColimit.ofId {X Y : C} (f : X ⟶ Y) (hf : f = 0) :
    IsColimit (CokernelCofork.ofπ (𝟙 Y) (show f ≫ 𝟙 Y = 0 by rw [hf, zero_comp])) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ (𝟙 Y) ⋯)

full_name: CategoryTheory.Limits.CokernelCofork.IsColimit.ofEpiOfIsZero
code: /-- Any zero object identifies to the cokernel of a given epimorphisms. -/
def CokernelCofork.IsColimit.ofEpiOfIsZero {X Y : C} {f : X ⟶ Y} (c : CokernelCofork f)
    (hf : Epi f) (h : IsZero c.pt) : IsColimit c 
goal: CategoryTheory.Limits.IsColimit c

full_name: CategoryTheory.Limits.CokernelCofork.IsColimit.isIso_π
code: lemma CokernelCofork.IsColimit.isIso_π {X Y : C} {f : X ⟶ Y} (c : CokernelCofork f)
    (hc : IsColimit c) (hf : f = 0) : IsIso c.π 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.Cofork.π c)

full_name: CategoryTheory.Limits.CokernelCofork.mapOfIsColimit
code: /-- The morphism between points of cokernel coforks induced by a morphism
in the category of arrows. -/
def mapOfIsColimit {cc : CokernelCofork f} (hf : IsColimit cc) (cc' : CokernelCofork f')
    (φ : Arrow.mk f ⟶ Arrow.mk f') : cc.pt ⟶ cc'.pt 
goal: cc.pt ⟶ cc'.pt

full_name: CategoryTheory.Limits.CokernelCofork.π_mapOfIsColimit
code: @[reassoc (attr := simp)]
lemma π_mapOfIsColimit {cc : CokernelCofork f} (hf : IsColimit cc) (cc' : CokernelCofork f')
    (φ : Arrow.mk f ⟶ Arrow.mk f') :
    cc.π ≫ mapOfIsColimit hf cc' φ = φ.right ≫ cc'.π 
goal: CategoryTheory.Limits.Cofork.π cc ≫ CategoryTheory.Limits.CokernelCofork.mapOfIsColimit hf cc' φ =
  φ.right ≫ CategoryTheory.Limits.Cofork.π cc'

full_name: CategoryTheory.Limits.CokernelCofork.mapIsoOfIsColimit_inv
code: /-- The isomorphism between points of limit cokernel coforks induced by an isomorphism
in the category of arrows. -/
@[simps]
def mapIsoOfIsColimit {cc : CokernelCofork f} {cc' : CokernelCofork f'}
    (hf : IsColimit cc) (hf' : IsColimit cc')
    (φ : Arrow.mk f ≅ Arrow.mk f') : cc.pt ≅ cc'.pt 
goal: (CategoryTheory.Limits.CokernelCofork.mapIsoOfIsColimit hf hf' φ).inv =
  CategoryTheory.Limits.CokernelCofork.mapOfIsColimit hf' cc φ.inv

full_name: CategoryTheory.Limits.CokernelCofork.mapIsoOfIsColimit_hom
code: /-- The isomorphism between points of limit cokernel coforks induced by an isomorphism
in the category of arrows. -/
@[simps]
def mapIsoOfIsColimit {cc : CokernelCofork f} {cc' : CokernelCofork f'}
    (hf : IsColimit cc) (hf' : IsColimit cc')
    (φ : Arrow.mk f ≅ Arrow.mk f') : cc.pt ≅ cc'.pt 
goal: (CategoryTheory.Limits.CokernelCofork.mapIsoOfIsColimit hf hf' φ).hom =
  CategoryTheory.Limits.CokernelCofork.mapOfIsColimit hf cc' φ.hom

full_name: CategoryTheory.Limits.CokernelCofork.mapIsoOfIsColimit
code: /-- The isomorphism between points of limit cokernel coforks induced by an isomorphism
in the category of arrows. -/
@[simps]
def mapIsoOfIsColimit {cc : CokernelCofork f} {cc' : CokernelCofork f'}
    (hf : IsColimit cc) (hf' : IsColimit cc')
    (φ : Arrow.mk f ≅ Arrow.mk f') : cc.pt ≅ cc'.pt 
goal: cc.pt ≅ cc'.pt

full_name: CategoryTheory.Limits.cokernel
code: /-- The cokernel of a morphism, expressed as the coequalizer with the 0 morphism. -/
abbrev cokernel : C 
goal: C

full_name: CategoryTheory.Limits.cokernel.π
code: /-- The map from the target of `f` to `cokernel f`. -/
abbrev cokernel.π : Y ⟶ cokernel f 
goal: Y ⟶ CategoryTheory.Limits.cokernel f

full_name: CategoryTheory.Limits.coequalizer_as_cokernel
code: @[simp]
theorem coequalizer_as_cokernel : coequalizer.π f 0 = cokernel.π f 
goal: CategoryTheory.Limits.coequalizer.π f 0 = CategoryTheory.Limits.cokernel.π f

full_name: CategoryTheory.Limits.cokernel.condition
code: @[reassoc (attr := simp)]
theorem cokernel.condition : f ≫ cokernel.π f = 0 
goal: f ≫ CategoryTheory.Limits.cokernel.π f = 0

full_name: CategoryTheory.Limits.cokernelIsCokernel
code: /-- The cokernel built from `cokernel.π f` is colimiting. -/
def cokernelIsCokernel :
    IsColimit (Cofork.ofπ (cokernel.π f) ((cokernel.condition f).trans zero_comp.symm)) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.Cofork.ofπ (CategoryTheory.Limits.cokernel.π f) ⋯)

full_name: CategoryTheory.Limits.cokernel.desc
code: /-- Given any morphism `k : Y ⟶ W` such that `f ≫ k = 0`, `k` factors through `cokernel.π f`
    via `cokernel.desc : cokernel f ⟶ W`. -/
abbrev cokernel.desc {W : C} (k : Y ⟶ W) (h : f ≫ k = 0) : cokernel f ⟶ W 
goal: CategoryTheory.Limits.cokernel f ⟶ W

full_name: CategoryTheory.Limits.cokernel.π_desc
code: @[reassoc (attr := simp)]
theorem cokernel.π_desc {W : C} (k : Y ⟶ W) (h : f ≫ k = 0) :
    cokernel.π f ≫ cokernel.desc f k h = k 
goal: CategoryTheory.Limits.cokernel.π f ≫ CategoryTheory.Limits.cokernel.desc f k h = k

full_name: CategoryTheory.Limits.colimit_ι_zero_cokernel_desc
code: @[reassoc (attr := simp)]
lemma colimit_ι_zero_cokernel_desc {C : Type*} [Category C]
    [HasZeroMorphisms C] {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) (h : f ≫ g = 0) [HasCokernel f] :
    colimit.ι (parallelPair f 0) WalkingParallelPair.zero ≫ cokernel.desc f g h = 0 
goal: CategoryTheory.Limits.colimit.ι (CategoryTheory.Limits.parallelPair f 0)
      CategoryTheory.Limits.WalkingParallelPair.zero ≫
    CategoryTheory.Limits.cokernel.desc f g h =
  0

full_name: CategoryTheory.Limits.cokernel.desc_zero
code: @[simp]
theorem cokernel.desc_zero {W : C} {h} : cokernel.desc f (0 : Y ⟶ W) h = 0 
goal: CategoryTheory.Limits.cokernel.desc f 0 h = 0

full_name: CategoryTheory.Limits.cokernel.desc_epi
code: instance cokernel.desc_epi {W : C} (k : Y ⟶ W) (h : f ≫ k = 0) [Epi k] :
    Epi (cokernel.desc f k h) 
goal: CategoryTheory.Epi (CategoryTheory.Limits.cokernel.desc f k h)

full_name: CategoryTheory.Limits.cokernel.desc'
code: /-- Any morphism `k : Y ⟶ W` satisfying `f ≫ k = 0` induces `l : cokernel f ⟶ W` such that
    `cokernel.π f ≫ l = k`. -/
def cokernel.desc' {W : C} (k : Y ⟶ W) (h : f ≫ k = 0) :
    { l : cokernel f ⟶ W // cokernel.π f ≫ l = k } 
goal: { l // CategoryTheory.Limits.cokernel.π f ≫ l = k }

full_name: CategoryTheory.Limits.cokernel.map
code: /-- A commuting square induces a morphism of cokernels. -/
abbrev cokernel.map {X' Y' : C} (f' : X' ⟶ Y') [HasCokernel f'] (p : X ⟶ X') (q : Y ⟶ Y')
    (w : f ≫ q = p ≫ f') : cokernel f ⟶ cokernel f' 
goal: CategoryTheory.Limits.cokernel f ⟶ CategoryTheory.Limits.cokernel f'

full_name: CategoryTheory.Limits.cokernel.map_desc
code: /-- Given a commutative diagram
    X --f--> Y --g--> Z
    |        |        |
    |        |        |
    v        v        v
    X' -f'-> Y' -g'-> Z'
with horizontal arrows composing to zero,
then we obtain a commutative square
   cokernel f ---> Z
   |               |
   | cokernel.map  |
   |               |
   v               v
   cokernel f' --> Z'
-/
theorem cokernel.map_desc {X Y Z X' Y' Z' : C} (f : X ⟶ Y) [HasCokernel f] (g : Y ⟶ Z)
    (w : f ≫ g = 0) (f' : X' ⟶ Y') [HasCokernel f'] (g' : Y' ⟶ Z') (w' : f' ≫ g' = 0) (p : X ⟶ X')
    (q : Y ⟶ Y') (r : Z ⟶ Z') (h₁ : f ≫ q = p ≫ f') (h₂ : g ≫ r = q ≫ g') :
    cokernel.map f f' p q h₁ ≫ cokernel.desc f' g' w' = cokernel.desc f g w ≫ r 
goal: CategoryTheory.Limits.cokernel.map f f' p q h₁ ≫ CategoryTheory.Limits.cokernel.desc f' g' w' =
  CategoryTheory.Limits.cokernel.desc f g w ≫ r

full_name: CategoryTheory.Limits.cokernel.mapIso_hom
code: /-- A commuting square of isomorphisms induces an isomorphism of cokernels. -/
@[simps]
def cokernel.mapIso {X' Y' : C} (f' : X' ⟶ Y') [HasCokernel f'] (p : X ≅ X') (q : Y ≅ Y')
    (w : f ≫ q.hom = p.hom ≫ f') : cokernel f ≅ cokernel f' 
goal: (CategoryTheory.Limits.cokernel.mapIso f f' p q w).hom = CategoryTheory.Limits.cokernel.map f f' p.hom q.hom w

full_name: CategoryTheory.Limits.cokernel.mapIso
code: /-- A commuting square of isomorphisms induces an isomorphism of cokernels. -/
@[simps]
def cokernel.mapIso {X' Y' : C} (f' : X' ⟶ Y') [HasCokernel f'] (p : X ≅ X') (q : Y ≅ Y')
    (w : f ≫ q.hom = p.hom ≫ f') : cokernel f ≅ cokernel f' 
goal: CategoryTheory.Limits.cokernel f ≅ CategoryTheory.Limits.cokernel f'

full_name: CategoryTheory.Limits.cokernel.mapIso_inv
code: /-- A commuting square of isomorphisms induces an isomorphism of cokernels. -/
@[simps]
def cokernel.mapIso {X' Y' : C} (f' : X' ⟶ Y') [HasCokernel f'] (p : X ≅ X') (q : Y ≅ Y')
    (w : f ≫ q.hom = p.hom ≫ f') : cokernel f ≅ cokernel f' 
goal: (CategoryTheory.Limits.cokernel.mapIso f f' p q w).inv = CategoryTheory.Limits.cokernel.map f' f p.inv q.inv ⋯

full_name: CategoryTheory.Limits.cokernel.π_zero_isIso
code: /-- The cokernel of the zero morphism is an isomorphism -/
instance cokernel.π_zero_isIso : IsIso (cokernel.π (0 : X ⟶ Y)) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.cokernel.π 0)

full_name: CategoryTheory.Limits.eq_zero_of_mono_cokernel
code: theorem eq_zero_of_mono_cokernel [Mono (cokernel.π f)] : f = 0 
goal: f = 0

full_name: CategoryTheory.Limits.cokernelZeroIsoTarget
code: /-- The cokernel of a zero morphism is isomorphic to the target. -/
def cokernelZeroIsoTarget : cokernel (0 : X ⟶ Y) ≅ Y 
goal: CategoryTheory.Limits.cokernel 0 ≅ Y

full_name: CategoryTheory.Limits.cokernelZeroIsoTarget_hom
code: @[simp]
theorem cokernelZeroIsoTarget_hom :
    cokernelZeroIsoTarget.hom = cokernel.desc (0 : X ⟶ Y) (𝟙 Y) (by simp) 
goal: CategoryTheory.Limits.cokernelZeroIsoTarget.hom = CategoryTheory.Limits.cokernel.desc 0 (𝟙 Y) ⋯

full_name: CategoryTheory.Limits.cokernelZeroIsoTarget_inv
code: @[simp]
theorem cokernelZeroIsoTarget_inv : cokernelZeroIsoTarget.inv = cokernel.π (0 : X ⟶ Y) 
goal: CategoryTheory.Limits.cokernelZeroIsoTarget.inv = CategoryTheory.Limits.cokernel.π 0

full_name: CategoryTheory.Limits.cokernelIsoOfEq
code: /-- If two morphisms are known to be equal, then their cokernels are isomorphic. -/
def cokernelIsoOfEq {f g : X ⟶ Y} [HasCokernel f] [HasCokernel g] (h : f = g) :
    cokernel f ≅ cokernel g 
goal: CategoryTheory.Limits.cokernel f ≅ CategoryTheory.Limits.cokernel g

full_name: CategoryTheory.Limits.cokernelIsoOfEq_refl
code: @[simp]
theorem cokernelIsoOfEq_refl {h : f = f} : cokernelIsoOfEq h = Iso.refl (cokernel f) 
goal: CategoryTheory.Limits.cokernelIsoOfEq h = CategoryTheory.Iso.refl (CategoryTheory.Limits.cokernel f)

full_name: CategoryTheory.Limits.π_comp_cokernelIsoOfEq_hom
code: @[reassoc (attr := simp)]
theorem π_comp_cokernelIsoOfEq_hom {f g : X ⟶ Y} [HasCokernel f] [HasCokernel g] (h : f = g) :
    cokernel.π f ≫ (cokernelIsoOfEq h).hom = cokernel.π g 
goal: CategoryTheory.Limits.cokernel.π f ≫ (CategoryTheory.Limits.cokernelIsoOfEq h).hom = CategoryTheory.Limits.cokernel.π g

full_name: CategoryTheory.Limits.π_comp_cokernelIsoOfEq_inv
code: @[reassoc (attr := simp)]
theorem π_comp_cokernelIsoOfEq_inv {f g : X ⟶ Y} [HasCokernel f] [HasCokernel g] (h : f = g) :
    cokernel.π _ ≫ (cokernelIsoOfEq h).inv = cokernel.π _ 
goal: CategoryTheory.Limits.cokernel.π g ≫ (CategoryTheory.Limits.cokernelIsoOfEq h).inv = CategoryTheory.Limits.cokernel.π f

full_name: CategoryTheory.Limits.cokernelIsoOfEq_hom_comp_desc
code: @[reassoc (attr := simp)]
theorem cokernelIsoOfEq_hom_comp_desc {Z} {f g : X ⟶ Y} [HasCokernel f] [HasCokernel g] (h : f = g)
    (e : Y ⟶ Z) (he) :
    (cokernelIsoOfEq h).hom ≫ cokernel.desc _ e he = cokernel.desc _ e (by simp [h, he]) 
goal: (CategoryTheory.Limits.cokernelIsoOfEq h).hom ≫ CategoryTheory.Limits.cokernel.desc g e he =
  CategoryTheory.Limits.cokernel.desc f e ⋯

full_name: CategoryTheory.Limits.cokernelIsoOfEq_inv_comp_desc
code: @[reassoc (attr := simp)]
theorem cokernelIsoOfEq_inv_comp_desc {Z} {f g : X ⟶ Y} [HasCokernel f] [HasCokernel g] (h : f = g)
    (e : Y ⟶ Z) (he) :
    (cokernelIsoOfEq h).inv ≫ cokernel.desc _ e he = cokernel.desc _ e (by simp [← h, he]) 
goal: (CategoryTheory.Limits.cokernelIsoOfEq h).inv ≫ CategoryTheory.Limits.cokernel.desc f e he =
  CategoryTheory.Limits.cokernel.desc g e ⋯

full_name: CategoryTheory.Limits.cokernelIsoOfEq_trans
code: @[simp]
theorem cokernelIsoOfEq_trans {f g h : X ⟶ Y} [HasCokernel f] [HasCokernel g] [HasCokernel h]
    (w₁ : f = g) (w₂ : g = h) :
    cokernelIsoOfEq w₁ ≪≫ cokernelIsoOfEq w₂ = cokernelIsoOfEq (w₁.trans w₂) 
goal: CategoryTheory.Limits.cokernelIsoOfEq w₁ ≪≫ CategoryTheory.Limits.cokernelIsoOfEq w₂ =
  CategoryTheory.Limits.cokernelIsoOfEq ⋯

full_name: CategoryTheory.Limits.cokernel_not_mono_of_nonzero
code: theorem cokernel_not_mono_of_nonzero (w : f ≠ 0) : ¬Mono (cokernel.π f) 
goal: ¬CategoryTheory.Mono (CategoryTheory.Limits.cokernel.π f)

full_name: CategoryTheory.Limits.cokernel_not_iso_of_nonzero
code: theorem cokernel_not_iso_of_nonzero (w : f ≠ 0) : IsIso (cokernel.π f) → False 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.cokernel.π f) → False

full_name: CategoryTheory.Limits.hasCokernel_comp_iso
code: instance hasCokernel_comp_iso {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasCokernel f] [IsIso g] :
    HasCokernel (f ≫ g) 
goal: CategoryTheory.Limits.HasCokernel (f ≫ g)

full_name: CategoryTheory.Limits.cokernelCompIsIso
code: /-- When `g` is an isomorphism, the cokernel of `f ≫ g` is isomorphic to the cokernel of `f`.
-/
@[simps]
def cokernelCompIsIso {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasCokernel f] [IsIso g] :
    cokernel (f ≫ g) ≅ cokernel f 
goal: CategoryTheory.Limits.cokernel (f ≫ g) ≅ CategoryTheory.Limits.cokernel f

full_name: CategoryTheory.Limits.cokernelCompIsIso_inv
code: /-- When `g` is an isomorphism, the cokernel of `f ≫ g` is isomorphic to the cokernel of `f`.
-/
@[simps]
def cokernelCompIsIso {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasCokernel f] [IsIso g] :
    cokernel (f ≫ g) ≅ cokernel f 
goal: (CategoryTheory.Limits.cokernelCompIsIso f g).inv =
  CategoryTheory.Limits.cokernel.desc f (g ≫ CategoryTheory.Limits.cokernel.π (f ≫ g)) ⋯

full_name: CategoryTheory.Limits.cokernelCompIsIso_hom
code: /-- When `g` is an isomorphism, the cokernel of `f ≫ g` is isomorphic to the cokernel of `f`.
-/
@[simps]
def cokernelCompIsIso {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasCokernel f] [IsIso g] :
    cokernel (f ≫ g) ≅ cokernel f 
goal: (CategoryTheory.Limits.cokernelCompIsIso f g).hom =
  CategoryTheory.Limits.cokernel.desc (f ≫ g) (CategoryTheory.inv g ≫ CategoryTheory.Limits.cokernel.π f) ⋯

full_name: CategoryTheory.Limits.hasCokernel_epi_comp
code: instance hasCokernel_epi_comp {X Y : C} (f : X ⟶ Y) [HasCokernel f] {W} (g : W ⟶ X) [Epi g] :
    HasCokernel (g ≫ f) 
goal: CategoryTheory.Limits.HasCokernel (g ≫ f)

full_name: CategoryTheory.Limits.cokernelEpiComp_hom
code: /-- When `f` is an epimorphism, the cokernel of `f ≫ g` is isomorphic to the cokernel of `g`.
-/
@[simps]
def cokernelEpiComp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [Epi f] [HasCokernel g] :
    cokernel (f ≫ g) ≅ cokernel g 
goal: (CategoryTheory.Limits.cokernelEpiComp f g).hom =
  CategoryTheory.Limits.cokernel.desc (f ≫ g) (CategoryTheory.Limits.cokernel.π g) ⋯

full_name: CategoryTheory.Limits.cokernelEpiComp_inv
code: /-- When `f` is an epimorphism, the cokernel of `f ≫ g` is isomorphic to the cokernel of `g`.
-/
@[simps]
def cokernelEpiComp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [Epi f] [HasCokernel g] :
    cokernel (f ≫ g) ≅ cokernel g 
goal: (CategoryTheory.Limits.cokernelEpiComp f g).inv =
  CategoryTheory.Limits.cokernel.desc g (CategoryTheory.Limits.cokernel.π (f ≫ g)) ⋯

full_name: CategoryTheory.Limits.cokernelEpiComp
code: /-- When `f` is an epimorphism, the cokernel of `f ≫ g` is isomorphic to the cokernel of `g`.
-/
@[simps]
def cokernelEpiComp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [Epi f] [HasCokernel g] :
    cokernel (f ≫ g) ≅ cokernel g 
goal: CategoryTheory.Limits.cokernel (f ≫ g) ≅ CategoryTheory.Limits.cokernel g

full_name: CategoryTheory.Limits.cokernel.zeroCokernelCofork
code: /-- The morphism to the zero object determines a cocone on a cokernel diagram -/
def cokernel.zeroCokernelCofork : CokernelCofork f 
goal: CategoryTheory.Limits.CokernelCofork f

full_name: CategoryTheory.Limits.cokernel.isColimitCoconeZeroCocone
code: /-- The morphism to the zero object is a cokernel of an epimorphism -/
def cokernel.isColimitCoconeZeroCocone [Epi f] : IsColimit (cokernel.zeroCokernelCofork f) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.cokernel.zeroCokernelCofork f)

full_name: CategoryTheory.Limits.cokernel.ofEpi
code: /-- The cokernel of an epimorphism is isomorphic to the zero object -/
def cokernel.ofEpi [HasCokernel f] [Epi f] : cokernel f ≅ 0 
goal: CategoryTheory.Limits.cokernel f ≅ 0

full_name: CategoryTheory.Limits.cokernel.π_of_epi
code: /-- The cokernel morphism of an epimorphism is a zero morphism -/
theorem cokernel.π_of_epi [HasCokernel f] [Epi f] : cokernel.π f = 0 
goal: CategoryTheory.Limits.cokernel.π f = 0

full_name: CategoryTheory.Limits.MonoFactorisation.kernel_ι_comp
code: @[simp]
theorem MonoFactorisation.kernel_ι_comp [HasKernel f] (F : MonoFactorisation f) :
    kernel.ι f ≫ F.e = 0 
goal: CategoryTheory.Limits.kernel.ι f ≫ F.e = 0

full_name: CategoryTheory.Limits.cokernelImageι_hom
code: /-- The cokernel of the image inclusion of a morphism `f` is isomorphic to the cokernel of `f`.

(This result requires that the factorisation through the image is an epimorphism.
This holds in any category with equalizers.)
-/
@[simps]
def cokernelImageι {X Y : C} (f : X ⟶ Y) [HasImage f] [HasCokernel (image.ι f)] [HasCokernel f]
    [Epi (factorThruImage f)] : cokernel (image.ι f) ≅ cokernel f 
goal: (CategoryTheory.Limits.cokernelImageι f).hom =
  CategoryTheory.Limits.cokernel.desc (CategoryTheory.Limits.image.ι f) (CategoryTheory.Limits.cokernel.π f) ⋯

full_name: CategoryTheory.Limits.cokernelImageι_inv
code: /-- The cokernel of the image inclusion of a morphism `f` is isomorphic to the cokernel of `f`.

(This result requires that the factorisation through the image is an epimorphism.
This holds in any category with equalizers.)
-/
@[simps]
def cokernelImageι {X Y : C} (f : X ⟶ Y) [HasImage f] [HasCokernel (image.ι f)] [HasCokernel f]
    [Epi (factorThruImage f)] : cokernel (image.ι f) ≅ cokernel f 
goal: (CategoryTheory.Limits.cokernelImageι f).inv =
  CategoryTheory.Limits.cokernel.desc f (CategoryTheory.Limits.cokernel.π (CategoryTheory.Limits.image.ι f)) ⋯

full_name: CategoryTheory.Limits.cokernelImageι
code: /-- The cokernel of the image inclusion of a morphism `f` is isomorphic to the cokernel of `f`.

(This result requires that the factorisation through the image is an epimorphism.
This holds in any category with equalizers.)
-/
@[simps]
def cokernelImageι {X Y : C} (f : X ⟶ Y) [HasImage f] [HasCokernel (image.ι f)] [HasCokernel f]
    [Epi (factorThruImage f)] : cokernel (image.ι f) ≅ cokernel f 
goal: CategoryTheory.Limits.cokernel (CategoryTheory.Limits.image.ι f) ≅ CategoryTheory.Limits.cokernel f

full_name: CategoryTheory.Limits.cokernel.π_of_zero
code: /-- The cokernel of a zero morphism is an isomorphism -/
theorem cokernel.π_of_zero : IsIso (cokernel.π (0 : X ⟶ Y)) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.cokernel.π 0)

full_name: CategoryTheory.Limits.kernel.of_cokernel_of_epi
code: /-- The kernel of the cokernel of an epimorphism is an isomorphism -/
instance kernel.of_cokernel_of_epi [HasCokernel f] [HasKernel (cokernel.π f)] [Epi f] :
    IsIso (kernel.ι (cokernel.π f)) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.kernel.ι (CategoryTheory.Limits.cokernel.π f))

full_name: CategoryTheory.Limits.cokernel.of_kernel_of_mono
code: /-- The cokernel of the kernel of a monomorphism is an isomorphism -/
instance cokernel.of_kernel_of_mono [HasKernel f] [HasCokernel (kernel.ι f)] [Mono f] :
    IsIso (cokernel.π (kernel.ι f)) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.cokernel.π (CategoryTheory.Limits.kernel.ι f))

full_name: CategoryTheory.Limits.zeroCokernelOfZeroCancel
code: /-- If `f ≫ g = 0` implies `g = 0` for all `g`, then `0 : Y ⟶ 0` is a cokernel of `f`. -/
def zeroCokernelOfZeroCancel {X Y : C} (f : X ⟶ Y)
    (hf : ∀ (Z : C) (g : Y ⟶ Z) (_ : f ≫ g = 0), g = 0) :
    IsColimit (CokernelCofork.ofπ (0 : Y ⟶ 0) (show f ≫ 0 = 0 by simp)) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ 0 ⋯)

full_name: CategoryTheory.Limits.IsCokernel.ofIsoComp
code: /-- If `i` is an isomorphism such that `i.hom ≫ l = f`, then any cokernel of `f` is a cokernel of
    `l`. -/
def IsCokernel.ofIsoComp {Z : C} (l : Z ⟶ Y) (i : X ≅ Z) (h : i.hom ≫ l = f) {s : CokernelCofork f}
    (hs : IsColimit s) :
    IsColimit
      (CokernelCofork.ofπ (Cofork.π s) <| show l ≫ Cofork.π s = 0 by simp [i.eq_inv_comp.2 h]) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ (CategoryTheory.Limits.Cofork.π s) ⋯)

full_name: CategoryTheory.Limits.cokernel.ofIsoComp
code: /-- If `i` is an isomorphism such that `i.hom ≫ l = f`, then the cokernel of `f` is a cokernel of
    `l`. -/
def cokernel.ofIsoComp [HasCokernel f] {Z : C} (l : Z ⟶ Y) (i : X ≅ Z) (h : i.hom ≫ l = f) :
    IsColimit
      (CokernelCofork.ofπ (cokernel.π f) <|
        show l ≫ cokernel.π f = 0 by simp [i.eq_inv_comp.2 h]) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ (CategoryTheory.Limits.cokernel.π f) ⋯)

full_name: CategoryTheory.Limits.IsCokernel.cokernelIso
code: /-- If `s` is any colimit cokernel cocone over `f` and `i` is an isomorphism such that
    `s.π ≫ i.hom = l`, then `l` is a cokernel of `f`. -/
def IsCokernel.cokernelIso {Z : C} (l : Y ⟶ Z) {s : CokernelCofork f} (hs : IsColimit s)
    (i : s.pt ≅ Z) (h : Cofork.π s ≫ i.hom = l) :
    IsColimit (CokernelCofork.ofπ l <| show f ≫ l = 0 by simp [← h]) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ l ⋯)

full_name: CategoryTheory.Limits.cokernel.cokernelIso
code: /-- If `i` is an isomorphism such that `cokernel.π f ≫ i.hom = l`, then `l` is a cokernel of `f`. -/
def cokernel.cokernelIso [HasCokernel f] {Z : C} (l : Y ⟶ Z) (i : cokernel f ≅ Z)
    (h : cokernel.π f ≫ i.hom = l) :
    IsColimit (@CokernelCofork.ofπ _ _ _ _ _ f _ l <| by simp [← h]) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.CokernelCofork.ofπ l ⋯)

full_name: CategoryTheory.Limits.kernelComparison
code: /-- The comparison morphism for the kernel of `f`.
This is an isomorphism iff `G` preserves the kernel of `f`; see
`CategoryTheory/Limits/Preserves/Shapes/Kernels.lean`
-/
def kernelComparison [HasKernel f] [HasKernel (G.map f)] : G.obj (kernel f) ⟶ kernel (G.map f) 
goal: G.obj (CategoryTheory.Limits.kernel f) ⟶ CategoryTheory.Limits.kernel (G.map f)

full_name: CategoryTheory.Limits.kernelComparison_comp_ι
code: @[reassoc (attr := simp)]
theorem kernelComparison_comp_ι [HasKernel f] [HasKernel (G.map f)] :
    kernelComparison f G ≫ kernel.ι (G.map f) = G.map (kernel.ι f) 
goal: CategoryTheory.Limits.kernelComparison f G ≫ CategoryTheory.Limits.kernel.ι (G.map f) =
  G.map (CategoryTheory.Limits.kernel.ι f)

full_name: CategoryTheory.Limits.map_lift_kernelComparison
code: @[reassoc (attr := simp)]
theorem map_lift_kernelComparison [HasKernel f] [HasKernel (G.map f)] {Z : C} {h : Z ⟶ X}
    (w : h ≫ f = 0) :
    G.map (kernel.lift _ h w) ≫ kernelComparison f G =
      kernel.lift _ (G.map h) (by simp only [← G.map_comp, w, Functor.map_zero]) 
goal: G.map (CategoryTheory.Limits.kernel.lift f h w) ≫ CategoryTheory.Limits.kernelComparison f G =
  CategoryTheory.Limits.kernel.lift (G.map f) (G.map h) ⋯

full_name: CategoryTheory.Limits.kernelComparison_comp_kernel_map
code: @[reassoc]
theorem kernelComparison_comp_kernel_map {X' Y' : C} [HasKernel f] [HasKernel (G.map f)]
    (g : X' ⟶ Y') [HasKernel g] [HasKernel (G.map g)] (p : X ⟶ X') (q : Y ⟶ Y')
    (hpq : f ≫ q = p ≫ g) :
    kernelComparison f G ≫
        kernel.map (G.map f) (G.map g) (G.map p) (G.map q) (by rw [← G.map_comp, hpq, G.map_comp]) =
      G.map (kernel.map f g p q hpq) ≫ kernelComparison g G 
goal: CategoryTheory.Limits.kernelComparison f G ≫
    CategoryTheory.Limits.kernel.map (G.map f) (G.map g) (G.map p) (G.map q) ⋯ =
  G.map (CategoryTheory.Limits.kernel.map f g p q hpq) ≫ CategoryTheory.Limits.kernelComparison g G

full_name: CategoryTheory.Limits.cokernelComparison
code: /-- The comparison morphism for the cokernel of `f`. -/
def cokernelComparison [HasCokernel f] [HasCokernel (G.map f)] :
    cokernel (G.map f) ⟶ G.obj (cokernel f) 
goal: CategoryTheory.Limits.cokernel (G.map f) ⟶ G.obj (CategoryTheory.Limits.cokernel f)

full_name: CategoryTheory.Limits.π_comp_cokernelComparison
code: @[reassoc (attr := simp)]
theorem π_comp_cokernelComparison [HasCokernel f] [HasCokernel (G.map f)] :
    cokernel.π (G.map f) ≫ cokernelComparison f G = G.map (cokernel.π _) 
goal: CategoryTheory.Limits.cokernel.π (G.map f) ≫ CategoryTheory.Limits.cokernelComparison f G =
  G.map (CategoryTheory.Limits.cokernel.π f)

full_name: CategoryTheory.Limits.cokernelComparison_map_desc
code: @[reassoc (attr := simp)]
theorem cokernelComparison_map_desc [HasCokernel f] [HasCokernel (G.map f)] {Z : C} {h : Y ⟶ Z}
    (w : f ≫ h = 0) :
    cokernelComparison f G ≫ G.map (cokernel.desc _ h w) =
      cokernel.desc _ (G.map h) (by simp only [← G.map_comp, w, Functor.map_zero]) 
goal: CategoryTheory.Limits.cokernelComparison f G ≫ G.map (CategoryTheory.Limits.cokernel.desc f h w) =
  CategoryTheory.Limits.cokernel.desc (G.map f) (G.map h) ⋯

full_name: CategoryTheory.Limits.cokernel_map_comp_cokernelComparison
code: @[reassoc]
theorem cokernel_map_comp_cokernelComparison {X' Y' : C} [HasCokernel f] [HasCokernel (G.map f)]
    (g : X' ⟶ Y') [HasCokernel g] [HasCokernel (G.map g)] (p : X ⟶ X') (q : Y ⟶ Y')
    (hpq : f ≫ q = p ≫ g) :
    cokernel.map (G.map f) (G.map g) (G.map p) (G.map q) (by rw [← G.map_comp, hpq, G.map_comp]) ≫
        cokernelComparison _ G =
      cokernelComparison _ G ≫ G.map (cokernel.map f g p q hpq) 
goal: CategoryTheory.Limits.cokernel.map (G.map f) (G.map g) (G.map p) (G.map q) ⋯ ≫
    CategoryTheory.Limits.cokernelComparison g G =
  CategoryTheory.Limits.cokernelComparison f G ≫ G.map (CategoryTheory.Limits.cokernel.map f g p q hpq)

full_name: CategoryTheory.Limits.HasKernels.has_limit
code: /-- `HasKernels` represents the existence of kernels for every morphism. -/
class HasKernels : Prop where
  has_limit : ∀ {X Y : C} (f : X ⟶ Y), HasKernel f := by infer_instance
goal: CategoryTheory.Limits.HasKernel f

full_name: CategoryTheory.Limits.HasKernels
code: /-- `HasKernels` represents the existence of kernels for every morphism. -/
class HasKernels : Prop where
  has_limit : ∀ {X Y : C} (f : X ⟶ Y), HasKernel f := by infer_instance
goal: Prop

full_name: CategoryTheory.Limits.HasCokernels
code: /-- `HasCokernels` represents the existence of cokernels for every morphism. -/
class HasCokernels : Prop where
  has_colimit : ∀ {X Y : C} (f : X ⟶ Y), HasCokernel f := by infer_instance
goal: Prop

full_name: CategoryTheory.Limits.HasCokernels.has_colimit
code: /-- `HasCokernels` represents the existence of cokernels for every morphism. -/
class HasCokernels : Prop where
  has_colimit : ∀ {X Y : C} (f : X ⟶ Y), HasCokernel f := by infer_instance
goal: CategoryTheory.Limits.HasCokernel f

full_name: CategoryTheory.Limits.hasKernels_of_hasEqualizers
code: instance (priority := 100) hasKernels_of_hasEqualizers [HasEqualizers C] : HasKernels C 
goal: CategoryTheory.Limits.HasKernels C

full_name: CategoryTheory.Limits.hasCokernels_of_hasCoequalizers
code: instance (priority := 100) hasCokernels_of_hasCoequalizers [HasCoequalizers C] :
    HasCokernels C 
goal: CategoryTheory.Limits.HasCokernels C