File: Mathlib/Algebra/Homology/HomologicalComplex.lean

full_name: HomologicalComplex
code: /-- A `HomologicalComplex V c` with a "shape" controlled by `c : ComplexShape ι`
has chain groups `X i` (objects in `V`) indexed by `i : ι`,
and a differential `d i j` whenever `c.Rel i j`.

We in fact ask for differentials `d i j` for all `i j : ι`,
but have a field `shape` requiring that these are zero when not allowed by `c`.
This avoids a lot of dependent type theory hell!

The composite of any two differentials `d i j ≫ d j k` must be zero.
-/
structure HomologicalComplex (c : ComplexShape ι) where
  X : ι → V
  d : ∀ i j, X i ⟶ X j
  shape : ∀ i j, ¬c.Rel i j → d i j = 0 := by aesop_cat
  d_comp_d' : ∀ i j k, c.Rel i j → c.Rel j k → d i j ≫ d j k = 0 := by aesop_cat
goal: Type (max (max u u_1) v)

full_name: HomologicalComplex.d_comp_d'
code: /-- A `HomologicalComplex V c` with a "shape" controlled by `c : ComplexShape ι`
has chain groups `X i` (objects in `V`) indexed by `i : ι`,
and a differential `d i j` whenever `c.Rel i j`.

We in fact ask for differentials `d i j` for all `i j : ι`,
but have a field `shape` requiring that these are zero when not allowed by `c`.
This avoids a lot of dependent type theory hell!

The composite of any two differentials `d i j ≫ d j k` must be zero.
-/
structure HomologicalComplex (c : ComplexShape ι) where
  X : ι → V
  d : ∀ i j, X i ⟶ X j
  shape : ∀ i j, ¬c.Rel i j → d i j = 0 := by aesop_cat
  d_comp_d' : ∀ i j k, c.Rel i j → c.Rel j k → d i j ≫ d j k = 0 := by aesop_cat
goal: c.Rel i j → c.Rel j k → self.d i j ≫ self.d j k = 0

full_name: HomologicalComplex.shape
code: /-- A `HomologicalComplex V c` with a "shape" controlled by `c : ComplexShape ι`
has chain groups `X i` (objects in `V`) indexed by `i : ι`,
and a differential `d i j` whenever `c.Rel i j`.

We in fact ask for differentials `d i j` for all `i j : ι`,
but have a field `shape` requiring that these are zero when not allowed by `c`.
This avoids a lot of dependent type theory hell!

The composite of any two differentials `d i j ≫ d j k` must be zero.
-/
structure HomologicalComplex (c : ComplexShape ι) where
  X : ι → V
  d : ∀ i j, X i ⟶ X j
  shape : ∀ i j, ¬c.Rel i j → d i j = 0 := by aesop_cat
  d_comp_d' : ∀ i j k, c.Rel i j → c.Rel j k → d i j ≫ d j k = 0 := by aesop_cat
goal: ¬c.Rel i j → self.d i j = 0

full_name: HomologicalComplex.d
code: /-- A `HomologicalComplex V c` with a "shape" controlled by `c : ComplexShape ι`
has chain groups `X i` (objects in `V`) indexed by `i : ι`,
and a differential `d i j` whenever `c.Rel i j`.

We in fact ask for differentials `d i j` for all `i j : ι`,
but have a field `shape` requiring that these are zero when not allowed by `c`.
This avoids a lot of dependent type theory hell!

The composite of any two differentials `d i j ≫ d j k` must be zero.
-/
structure HomologicalComplex (c : ComplexShape ι) where
  X : ι → V
  d : ∀ i j, X i ⟶ X j
  shape : ∀ i j, ¬c.Rel i j → d i j = 0 := by aesop_cat
  d_comp_d' : ∀ i j k, c.Rel i j → c.Rel j k → d i j ≫ d j k = 0 := by aesop_cat
goal: self.X i ⟶ self.X j

full_name: HomologicalComplex.X
code: /-- A `HomologicalComplex V c` with a "shape" controlled by `c : ComplexShape ι`
has chain groups `X i` (objects in `V`) indexed by `i : ι`,
and a differential `d i j` whenever `c.Rel i j`.

We in fact ask for differentials `d i j` for all `i j : ι`,
but have a field `shape` requiring that these are zero when not allowed by `c`.
This avoids a lot of dependent type theory hell!

The composite of any two differentials `d i j ≫ d j k` must be zero.
-/
structure HomologicalComplex (c : ComplexShape ι) where
  X : ι → V
  d : ∀ i j, X i ⟶ X j
  shape : ∀ i j, ¬c.Rel i j → d i j = 0 := by aesop_cat
  d_comp_d' : ∀ i j k, c.Rel i j → c.Rel j k → d i j ≫ d j k = 0 := by aesop_cat
goal: ι → V

full_name: HomologicalComplex.d_comp_d
code: @[reassoc (attr := simp)]
theorem d_comp_d (C : HomologicalComplex V c) (i j k : ι) : C.d i j ≫ C.d j k = 0 
goal: C.d i j ≫ C.d j k = 0

full_name: HomologicalComplex.ext
code: theorem ext {C₁ C₂ : HomologicalComplex V c} (h_X : C₁.X = C₂.X)
    (h_d :
      ∀ i j : ι,
        c.Rel i j → C₁.d i j ≫ eqToHom (congr_fun h_X j) = eqToHom (congr_fun h_X i) ≫ C₂.d i j) :
    C₁ = C₂ 
goal: C₁ = C₂

full_name: HomologicalComplex.XIsoOfEq
code: /-- The obvious isomorphism `K.X p ≅ K.X q` when `p = q`. -/
def XIsoOfEq (K : HomologicalComplex V c) {p q : ι} (h : p = q) : K.X p ≅ K.X q 
goal: K.X p ≅ K.X q

full_name: HomologicalComplex.XIsoOfEq_rfl
code: @[simp]
lemma XIsoOfEq_rfl (K : HomologicalComplex V c) (p : ι) :
    K.XIsoOfEq (rfl : p = p) = Iso.refl _ 
goal: K.XIsoOfEq ⋯ = CategoryTheory.Iso.refl (K.X p)

full_name: HomologicalComplex.XIsoOfEq_hom_comp_XIsoOfEq_hom
code: @[reassoc (attr := simp)]
lemma XIsoOfEq_hom_comp_XIsoOfEq_hom (K : HomologicalComplex V c) {p₁ p₂ p₃ : ι}
    (h₁₂ : p₁ = p₂) (h₂₃ : p₂ = p₃) :
    (K.XIsoOfEq h₁₂).hom ≫ (K.XIsoOfEq h₂₃).hom = (K.XIsoOfEq (h₁₂.trans h₂₃)).hom 
goal: (K.XIsoOfEq h₁₂).hom ≫ (K.XIsoOfEq h₂₃).hom = (K.XIsoOfEq ⋯).hom

full_name: HomologicalComplex.XIsoOfEq_hom_comp_XIsoOfEq_inv
code: @[reassoc (attr := simp)]
lemma XIsoOfEq_hom_comp_XIsoOfEq_inv (K : HomologicalComplex V c) {p₁ p₂ p₃ : ι}
    (h₁₂ : p₁ = p₂) (h₃₂ : p₃ = p₂) :
    (K.XIsoOfEq h₁₂).hom ≫ (K.XIsoOfEq h₃₂).inv = (K.XIsoOfEq (h₁₂.trans h₃₂.symm)).hom 
goal: (K.XIsoOfEq h₁₂).hom ≫ (K.XIsoOfEq h₃₂).inv = (K.XIsoOfEq ⋯).hom

full_name: HomologicalComplex.XIsoOfEq_inv_comp_XIsoOfEq_hom
code: @[reassoc (attr := simp)]
lemma XIsoOfEq_inv_comp_XIsoOfEq_hom (K : HomologicalComplex V c) {p₁ p₂ p₃ : ι}
    (h₂₁ : p₂ = p₁) (h₂₃ : p₂ = p₃) :
    (K.XIsoOfEq h₂₁).inv ≫ (K.XIsoOfEq h₂₃).hom = (K.XIsoOfEq (h₂₁.symm.trans h₂₃)).hom 
goal: (K.XIsoOfEq h₂₁).inv ≫ (K.XIsoOfEq h₂₃).hom = (K.XIsoOfEq ⋯).hom

full_name: HomologicalComplex.XIsoOfEq_inv_comp_XIsoOfEq_inv
code: @[reassoc (attr := simp)]
lemma XIsoOfEq_inv_comp_XIsoOfEq_inv (K : HomologicalComplex V c) {p₁ p₂ p₃ : ι}
    (h₂₁ : p₂ = p₁) (h₃₂ : p₃ = p₂) :
    (K.XIsoOfEq h₂₁).inv ≫ (K.XIsoOfEq h₃₂).inv = (K.XIsoOfEq (h₃₂.trans h₂₁).symm).hom 
goal: (K.XIsoOfEq h₂₁).inv ≫ (K.XIsoOfEq h₃₂).inv = (K.XIsoOfEq ⋯).hom

full_name: HomologicalComplex.XIsoOfEq_hom_comp_d
code: @[reassoc (attr := simp)]
lemma XIsoOfEq_hom_comp_d (K : HomologicalComplex V c) {p₁ p₂ : ι} (h : p₁ = p₂) (p₃ : ι) :
    (K.XIsoOfEq h).hom ≫ K.d p₂ p₃ = K.d p₁ p₃ 
goal: (K.XIsoOfEq h).hom ≫ K.d p₂ p₃ = K.d p₁ p₃

full_name: HomologicalComplex.XIsoOfEq_inv_comp_d
code: @[reassoc (attr := simp)]
lemma XIsoOfEq_inv_comp_d (K : HomologicalComplex V c) {p₂ p₁ : ι} (h : p₂ = p₁) (p₃ : ι) :
    (K.XIsoOfEq h).inv ≫ K.d p₂ p₃ = K.d p₁ p₃ 
goal: (K.XIsoOfEq h).inv ≫ K.d p₂ p₃ = K.d p₁ p₃

full_name: HomologicalComplex.d_comp_XIsoOfEq_hom
code: @[reassoc (attr := simp)]
lemma d_comp_XIsoOfEq_hom (K : HomologicalComplex V c) {p₂ p₃ : ι} (h : p₂ = p₃) (p₁ : ι) :
    K.d p₁ p₂ ≫ (K.XIsoOfEq h).hom = K.d p₁ p₃ 
goal: K.d p₁ p₂ ≫ (K.XIsoOfEq h).hom = K.d p₁ p₃

full_name: HomologicalComplex.d_comp_XIsoOfEq_inv
code: @[reassoc (attr := simp)]
lemma d_comp_XIsoOfEq_inv (K : HomologicalComplex V c) {p₂ p₃ : ι} (h : p₃ = p₂) (p₁ : ι) :
    K.d p₁ p₂ ≫ (K.XIsoOfEq h).inv = K.d p₁ p₃ 
goal: K.d p₁ p₂ ≫ (K.XIsoOfEq h).inv = K.d p₁ p₃

full_name: ChainComplex
code: /-- An `α`-indexed chain complex is a `HomologicalComplex`
in which `d i j ≠ 0` only if `j + 1 = i`.
-/
abbrev ChainComplex (α : Type*) [AddRightCancelSemigroup α] [One α] : Type _ 
goal: Type (max (max u_2 u) v)

full_name: CochainComplex
code: /-- An `α`-indexed cochain complex is a `HomologicalComplex`
in which `d i j ≠ 0` only if `i + 1 = j`.
-/
abbrev CochainComplex (α : Type*) [AddRightCancelSemigroup α] [One α] : Type _ 
goal: Type (max (max u_2 u) v)

full_name: ChainComplex.prev
code: @[simp]
theorem prev (α : Type*) [AddRightCancelSemigroup α] [One α] (i : α) :
    (ComplexShape.down α).prev i = i + 1 
goal: (ComplexShape.down α).prev i = i + 1

full_name: ChainComplex.next
code: @[simp]
theorem next (α : Type*) [AddGroup α] [One α] (i : α) : (ComplexShape.down α).next i = i - 1 
goal: (ComplexShape.down α).next i = i - 1

full_name: ChainComplex.next_nat_zero
code: @[simp]
theorem next_nat_zero : (ComplexShape.down ℕ).next 0 = 0 
goal: (ComplexShape.down ℕ).next 0 = 0

full_name: ChainComplex.next_nat_succ
code: @[simp]
theorem next_nat_succ (i : ℕ) : (ComplexShape.down ℕ).next (i + 1) = i 
goal: (ComplexShape.down ℕ).next (i + 1) = i

full_name: CochainComplex.prev
code: @[simp]
theorem prev (α : Type*) [AddGroup α] [One α] (i : α) : (ComplexShape.up α).prev i = i - 1 
goal: (ComplexShape.up α).prev i = i - 1

full_name: CochainComplex.next
code: @[simp]
theorem next (α : Type*) [AddRightCancelSemigroup α] [One α] (i : α) :
    (ComplexShape.up α).next i = i + 1 
goal: (ComplexShape.up α).next i = i + 1

full_name: CochainComplex.prev_nat_zero
code: @[simp]
theorem prev_nat_zero : (ComplexShape.up ℕ).prev 0 = 0 
goal: (ComplexShape.up ℕ).prev 0 = 0

full_name: CochainComplex.prev_nat_succ
code: @[simp]
theorem prev_nat_succ (i : ℕ) : (ComplexShape.up ℕ).prev (i + 1) = i 
goal: (ComplexShape.up ℕ).prev (i + 1) = i

full_name: HomologicalComplex.Hom.comm'
code: /-- A morphism of homological complexes consists of maps between the chain groups,
commuting with the differentials.
-/
@[ext]
structure Hom (A B : HomologicalComplex V c) where
  f : ∀ i, A.X i ⟶ B.X i
  comm' : ∀ i j, c.Rel i j → f i ≫ B.d i j = A.d i j ≫ f j := by aesop_cat
goal: c.Rel i j → self.f i ≫ B.d i j = A.d i j ≫ self.f j

full_name: HomologicalComplex.Hom
code: /-- A morphism of homological complexes consists of maps between the chain groups,
commuting with the differentials.
-/
@[ext]
structure Hom (A B : HomologicalComplex V c) where
  f : ∀ i, A.X i ⟶ B.X i
  comm' : ∀ i j, c.Rel i j → f i ≫ B.d i j = A.d i j ≫ f j := by aesop_cat
goal: Type (max u_1 v)

full_name: HomologicalComplex.Hom.f
code: /-- A morphism of homological complexes consists of maps between the chain groups,
commuting with the differentials.
-/
@[ext]
structure Hom (A B : HomologicalComplex V c) where
  f : ∀ i, A.X i ⟶ B.X i
  comm' : ∀ i j, c.Rel i j → f i ≫ B.d i j = A.d i j ≫ f j := by aesop_cat
goal: A.X i ⟶ B.X i

full_name: HomologicalComplex.Hom.comm
code: @[reassoc (attr := simp)]
theorem Hom.comm {A B : HomologicalComplex V c} (f : A.Hom B) (i j : ι) :
    f.f i ≫ B.d i j = A.d i j ≫ f.f j 
goal: f.f i ≫ B.d i j = A.d i j ≫ f.f j

full_name: HomologicalComplex.instInhabitedHom
code: instance (A B : HomologicalComplex V c) : Inhabited (Hom A B) 
goal: Inhabited (A.Hom B)

full_name: HomologicalComplex.id
code: /-- Identity chain map. -/
def id (A : HomologicalComplex V c) : Hom A A 
goal: A.Hom A

full_name: HomologicalComplex.comp
code: /-- Composition of chain maps. -/
def comp (A B C : HomologicalComplex V c) (φ : Hom A B) (ψ : Hom B C) : Hom A C 
goal: A.Hom C

full_name: HomologicalComplex.instCategory
code: instance : Category (HomologicalComplex V c) 
goal: CategoryTheory.Category.{max u_1 v, max (max u_1 u) v} (HomologicalComplex V c)

full_name: HomologicalComplex.hom_ext
code: @[ext]
lemma hom_ext {C D : HomologicalComplex V c} (f g : C ⟶ D)
    (h : ∀ i, f.f i = g.f i) : f = g 
goal: f = g

full_name: HomologicalComplex.id_f
code: @[simp]
theorem id_f (C : HomologicalComplex V c) (i : ι) : Hom.f (𝟙 C) i = 𝟙 (C.X i) 
goal: (𝟙 C).f i = 𝟙 (C.X i)

full_name: HomologicalComplex.comp_f
code: @[simp, reassoc]
theorem comp_f {C₁ C₂ C₃ : HomologicalComplex V c} (f : C₁ ⟶ C₂) (g : C₂ ⟶ C₃) (i : ι) :
    (f ≫ g).f i = f.f i ≫ g.f i 
goal: (f ≫ g).f i = f.f i ≫ g.f i

full_name: HomologicalComplex.eqToHom_f
code: @[simp]
theorem eqToHom_f {C₁ C₂ : HomologicalComplex V c} (h : C₁ = C₂) (n : ι) :
    HomologicalComplex.Hom.f (eqToHom h) n =
      eqToHom (congr_fun (congr_arg HomologicalComplex.X h) n) 
goal: (CategoryTheory.eqToHom h).f n = CategoryTheory.eqToHom ⋯

full_name: HomologicalComplex.hom_f_injective
code: theorem hom_f_injective {C₁ C₂ : HomologicalComplex V c} :
    Function.Injective fun f : Hom C₁ C₂ => f.f 
goal: Function.Injective fun f => f.f

full_name: HomologicalComplex.instZeroHom
code: instance (X Y : HomologicalComplex V c) : Zero (X ⟶ Y) 
goal: Zero (X ⟶ Y)

full_name: HomologicalComplex.zero_f
code: @[simp]
theorem zero_f (C D : HomologicalComplex V c) (i : ι) : (0 : C ⟶ D).f i = 0 
goal: HomologicalComplex.Hom.f 0 i = 0

full_name: HomologicalComplex.instHasZeroMorphisms
code: instance : HasZeroMorphisms (HomologicalComplex V c) 
goal: CategoryTheory.Limits.HasZeroMorphisms (HomologicalComplex V c)

full_name: HomologicalComplex.zero
code: /-- The zero complex -/
noncomputable def zero [HasZeroObject V] : HomologicalComplex V c 
goal: HomologicalComplex V c

full_name: HomologicalComplex.isZero_zero
code: theorem isZero_zero [HasZeroObject V] : IsZero (zero : HomologicalComplex V c) 
goal: CategoryTheory.Limits.IsZero HomologicalComplex.zero

full_name: HomologicalComplex.instHasZeroObject
code: instance [HasZeroObject V] : HasZeroObject (HomologicalComplex V c) 
goal: CategoryTheory.Limits.HasZeroObject (HomologicalComplex V c)

full_name: HomologicalComplex.instInhabitedOfHasZeroObject
code: noncomputable instance [HasZeroObject V] : Inhabited (HomologicalComplex V c) 
goal: Inhabited (HomologicalComplex V c)

full_name: HomologicalComplex.congr_hom
code: theorem congr_hom {C D : HomologicalComplex V c} {f g : C ⟶ D} (w : f = g) (i : ι) :
    f.f i = g.f i 
goal: f.f i = g.f i

full_name: HomologicalComplex.mono_of_mono_f
code: lemma mono_of_mono_f {K L : HomologicalComplex V c} (φ : K ⟶ L)
    (hφ : ∀ i, Mono (φ.f i)) : Mono φ 
goal: CategoryTheory.Mono φ

full_name: HomologicalComplex.epi_of_epi_f
code: lemma epi_of_epi_f {K L : HomologicalComplex V c} (φ : K ⟶ L)
    (hφ : ∀ i, Epi (φ.f i)) : Epi φ 
goal: CategoryTheory.Epi φ

full_name: HomologicalComplex.eval_obj
code: /-- The functor picking out the `i`-th object of a complex. -/
@[simps]
def eval (i : ι) : HomologicalComplex V c ⥤ V 
goal: (HomologicalComplex.eval V c i).obj C = C.X i

full_name: HomologicalComplex.eval
code: /-- The functor picking out the `i`-th object of a complex. -/
@[simps]
def eval (i : ι) : HomologicalComplex V c ⥤ V 
goal: HomologicalComplex V c ⥤ V

full_name: HomologicalComplex.eval_map
code: /-- The functor picking out the `i`-th object of a complex. -/
@[simps]
def eval (i : ι) : HomologicalComplex V c ⥤ V 
goal: ∀ {X Y : HomologicalComplex V c} (f : X ⟶ Y), (HomologicalComplex.eval V c i).map f = f.f i

full_name: HomologicalComplex.instPreservesZeroMorphismsEval
code: instance (i : ι) : (eval V c i).PreservesZeroMorphisms 
goal: (HomologicalComplex.eval V c i).PreservesZeroMorphisms

full_name: HomologicalComplex.forget
code: /-- The functor forgetting the differential in a complex, obtaining a graded object. -/
@[simps]
def forget : HomologicalComplex V c ⥤ GradedObject ι V 
goal: HomologicalComplex V c ⥤ CategoryTheory.GradedObject ι V

full_name: HomologicalComplex.forget_map
code: /-- The functor forgetting the differential in a complex, obtaining a graded object. -/
@[simps]
def forget : HomologicalComplex V c ⥤ GradedObject ι V 
goal: ∀ {X Y : HomologicalComplex V c} (f : X ⟶ Y) (i : ι), (HomologicalComplex.forget V c).map f i = f.f i

full_name: HomologicalComplex.forget_obj
code: /-- The functor forgetting the differential in a complex, obtaining a graded object. -/
@[simps]
def forget : HomologicalComplex V c ⥤ GradedObject ι V 
goal: ∀ (a : ι), (HomologicalComplex.forget V c).obj C a = C.X a

full_name: HomologicalComplex.instFaithfulGradedObjectForget
code: instance : (forget V c).Faithful 
goal: (HomologicalComplex.forget V c).Faithful

full_name: HomologicalComplex.forgetEval_inv_app
code: /-- Forgetting the differentials than picking out the `i`-th object is the same as
just picking out the `i`-th object. -/
@[simps!]
def forgetEval (i : ι) : forget V c ⋙ GradedObject.eval i ≅ eval V c i 
goal: (HomologicalComplex.forgetEval V c i).inv.app X = 𝟙 (X.X i)

full_name: HomologicalComplex.forgetEval
code: /-- Forgetting the differentials than picking out the `i`-th object is the same as
just picking out the `i`-th object. -/
@[simps!]
def forgetEval (i : ι) : forget V c ⋙ GradedObject.eval i ≅ eval V c i 
goal: HomologicalComplex.forget V c ⋙ CategoryTheory.GradedObject.eval i ≅ HomologicalComplex.eval V c i

full_name: HomologicalComplex.forgetEval_hom_app
code: /-- Forgetting the differentials than picking out the `i`-th object is the same as
just picking out the `i`-th object. -/
@[simps!]
def forgetEval (i : ι) : forget V c ⋙ GradedObject.eval i ≅ eval V c i 
goal: (HomologicalComplex.forgetEval V c i).hom.app X = 𝟙 (X.X i)

full_name: HomologicalComplex.XIsoOfEq_hom_naturality
code: @[reassoc]
lemma XIsoOfEq_hom_naturality {K L : HomologicalComplex V c} (φ : K ⟶ L) {n n' : ι} (h : n = n') :
    φ.f n ≫ (L.XIsoOfEq h).hom = (K.XIsoOfEq h).hom ≫ φ.f n' 
goal: φ.f n ≫ (L.XIsoOfEq h).hom = (K.XIsoOfEq h).hom ≫ φ.f n'

full_name: HomologicalComplex.XIsoOfEq_inv_naturality
code: @[reassoc]
lemma XIsoOfEq_inv_naturality {K L : HomologicalComplex V c} (φ : K ⟶ L) {n n' : ι} (h : n = n') :
    φ.f n' ≫ (L.XIsoOfEq h).inv = (K.XIsoOfEq h).inv ≫ φ.f n 
goal: φ.f n' ≫ (L.XIsoOfEq h).inv = (K.XIsoOfEq h).inv ≫ φ.f n

full_name: HomologicalComplex.d_comp_eqToHom
code: /-- If `C.d i j` and `C.d i j'` are both allowed, then we must have `j = j'`,
and so the differentials only differ by an `eqToHom`.
-/
theorem d_comp_eqToHom {i j j' : ι} (rij : c.Rel i j) (rij' : c.Rel i j') :
    C.d i j' ≫ eqToHom (congr_arg C.X (c.next_eq rij' rij)) = C.d i j 
goal: C.d i j' ≫ CategoryTheory.eqToHom ⋯ = C.d i j

full_name: HomologicalComplex.eqToHom_comp_d
code: /-- If `C.d i j` and `C.d i' j` are both allowed, then we must have `i = i'`,
and so the differentials only differ by an `eqToHom`.
-/
theorem eqToHom_comp_d {i i' j : ι} (rij : c.Rel i j) (rij' : c.Rel i' j) :
    eqToHom (congr_arg C.X (c.prev_eq rij rij')) ≫ C.d i' j = C.d i j 
goal: CategoryTheory.eqToHom ⋯ ≫ C.d i' j = C.d i j

full_name: HomologicalComplex.kernel_eq_kernel
code: theorem kernel_eq_kernel [HasKernels V] {i j j' : ι} (r : c.Rel i j) (r' : c.Rel i j') :
    kernelSubobject (C.d i j) = kernelSubobject (C.d i j') 
goal: CategoryTheory.Limits.kernelSubobject (C.d i j) = CategoryTheory.Limits.kernelSubobject (C.d i j')

full_name: HomologicalComplex.image_eq_image
code: theorem image_eq_image [HasImages V] [HasEqualizers V] {i i' j : ι} (r : c.Rel i j)
    (r' : c.Rel i' j) : imageSubobject (C.d i j) = imageSubobject (C.d i' j) 
goal: CategoryTheory.Limits.imageSubobject (C.d i j) = CategoryTheory.Limits.imageSubobject (C.d i' j)

full_name: HomologicalComplex.xPrev
code: /-- Either `C.X i`, if there is some `i` with `c.Rel i j`, or `C.X j`. -/
abbrev xPrev (j : ι) : V 
goal: V

full_name: HomologicalComplex.xPrevIso
code: /-- If `c.Rel i j`, then `C.xPrev j` is isomorphic to `C.X i`. -/
def xPrevIso {i j : ι} (r : c.Rel i j) : C.xPrev j ≅ C.X i 
goal: C.xPrev j ≅ C.X i

full_name: HomologicalComplex.xPrevIsoSelf
code: /-- If there is no `i` so `c.Rel i j`, then `C.xPrev j` is isomorphic to `C.X j`. -/
def xPrevIsoSelf {j : ι} (h : ¬c.Rel (c.prev j) j) : C.xPrev j ≅ C.X j 
goal: C.xPrev j ≅ C.X j

full_name: HomologicalComplex.xNext
code: /-- Either `C.X j`, if there is some `j` with `c.rel i j`, or `C.X i`. -/
abbrev xNext (i : ι) : V 
goal: V

full_name: HomologicalComplex.xNextIso
code: /-- If `c.Rel i j`, then `C.xNext i` is isomorphic to `C.X j`. -/
def xNextIso {i j : ι} (r : c.Rel i j) : C.xNext i ≅ C.X j 
goal: C.xNext i ≅ C.X j

full_name: HomologicalComplex.xNextIsoSelf
code: /-- If there is no `j` so `c.Rel i j`, then `C.xNext i` is isomorphic to `C.X i`. -/
def xNextIsoSelf {i : ι} (h : ¬c.Rel i (c.next i)) : C.xNext i ≅ C.X i 
goal: C.xNext i ≅ C.X i

full_name: HomologicalComplex.dTo
code: /-- The differential mapping into `C.X j`, or zero if there isn't one.
-/
abbrev dTo (j : ι) : C.xPrev j ⟶ C.X j 
goal: C.xPrev j ⟶ C.X j

full_name: HomologicalComplex.dFrom
code: /-- The differential mapping out of `C.X i`, or zero if there isn't one.
-/
abbrev dFrom (i : ι) : C.X i ⟶ C.xNext i 
goal: C.X i ⟶ C.xNext i

full_name: HomologicalComplex.dTo_eq
code: theorem dTo_eq {i j : ι} (r : c.Rel i j) : C.dTo j = (C.xPrevIso r).hom ≫ C.d i j 
goal: C.dTo j = (C.xPrevIso r).hom ≫ C.d i j

full_name: HomologicalComplex.dTo_eq_zero
code: @[simp]
theorem dTo_eq_zero {j : ι} (h : ¬c.Rel (c.prev j) j) : C.dTo j = 0 
goal: C.dTo j = 0

full_name: HomologicalComplex.dFrom_eq
code: theorem dFrom_eq {i j : ι} (r : c.Rel i j) : C.dFrom i = C.d i j ≫ (C.xNextIso r).inv 
goal: C.dFrom i = C.d i j ≫ (C.xNextIso r).inv

full_name: HomologicalComplex.dFrom_eq_zero
code: @[simp]
theorem dFrom_eq_zero {i : ι} (h : ¬c.Rel i (c.next i)) : C.dFrom i = 0 
goal: C.dFrom i = 0

full_name: HomologicalComplex.xPrevIso_comp_dTo
code: @[reassoc (attr := simp)]
theorem xPrevIso_comp_dTo {i j : ι} (r : c.Rel i j) : (C.xPrevIso r).inv ≫ C.dTo j = C.d i j 
goal: (C.xPrevIso r).inv ≫ C.dTo j = C.d i j

full_name: HomologicalComplex.xPrevIsoSelf_comp_dTo
code: @[reassoc (attr := simp)]
theorem xPrevIsoSelf_comp_dTo {j : ι} (h : ¬c.Rel (c.prev j) j) :
    (C.xPrevIsoSelf h).inv ≫ C.dTo j = 0 
goal: (C.xPrevIsoSelf h).inv ≫ C.dTo j = 0

full_name: HomologicalComplex.dFrom_comp_xNextIso
code: @[reassoc (attr := simp)]
theorem dFrom_comp_xNextIso {i j : ι} (r : c.Rel i j) :
    C.dFrom i ≫ (C.xNextIso r).hom = C.d i j 
goal: C.dFrom i ≫ (C.xNextIso r).hom = C.d i j

full_name: HomologicalComplex.dFrom_comp_xNextIsoSelf
code: @[reassoc (attr := simp)]
theorem dFrom_comp_xNextIsoSelf {i : ι} (h : ¬c.Rel i (c.next i)) :
    C.dFrom i ≫ (C.xNextIsoSelf h).hom = 0 
goal: C.dFrom i ≫ (C.xNextIsoSelf h).hom = 0

full_name: HomologicalComplex.dTo_comp_dFrom
code: @[simp 1100]
theorem dTo_comp_dFrom (j : ι) : C.dTo j ≫ C.dFrom j = 0 
goal: C.dTo j ≫ C.dFrom j = 0

full_name: HomologicalComplex.kernel_from_eq_kernel
code: theorem kernel_from_eq_kernel [HasKernels V] {i j : ι} (r : c.Rel i j) :
    kernelSubobject (C.dFrom i) = kernelSubobject (C.d i j) 
goal: CategoryTheory.Limits.kernelSubobject (C.dFrom i) = CategoryTheory.Limits.kernelSubobject (C.d i j)

full_name: HomologicalComplex.image_to_eq_image
code: theorem image_to_eq_image [HasImages V] [HasEqualizers V] {i j : ι} (r : c.Rel i j) :
    imageSubobject (C.dTo j) = imageSubobject (C.d i j) 
goal: CategoryTheory.Limits.imageSubobject (C.dTo j) = CategoryTheory.Limits.imageSubobject (C.d i j)

full_name: HomologicalComplex.Hom.isoApp
code: /-- The `i`-th component of an isomorphism of chain complexes. -/
@[simps!]
def isoApp (f : C₁ ≅ C₂) (i : ι) : C₁.X i ≅ C₂.X i 
goal: C₁.X i ≅ C₂.X i

full_name: HomologicalComplex.Hom.isoApp_hom
code: /-- The `i`-th component of an isomorphism of chain complexes. -/
@[simps!]
def isoApp (f : C₁ ≅ C₂) (i : ι) : C₁.X i ≅ C₂.X i 
goal: (HomologicalComplex.Hom.isoApp f i).hom = f.hom.f i

full_name: HomologicalComplex.Hom.isoApp_inv
code: /-- The `i`-th component of an isomorphism of chain complexes. -/
@[simps!]
def isoApp (f : C₁ ≅ C₂) (i : ι) : C₁.X i ≅ C₂.X i 
goal: (HomologicalComplex.Hom.isoApp f i).inv = f.inv.f i

full_name: HomologicalComplex.Hom.isoOfComponents_hom_f
code: /-- Construct an isomorphism of chain complexes from isomorphism of the objects
which commute with the differentials. -/
@[simps]
def isoOfComponents (f : ∀ i, C₁.X i ≅ C₂.X i)
    (hf : ∀ i j, c.Rel i j → (f i).hom ≫ C₂.d i j = C₁.d i j ≫ (f j).hom := by aesop_cat) :
    C₁ ≅ C₂ 
goal: (HomologicalComplex.Hom.isoOfComponents f hf).hom.f i = (f i).hom

full_name: HomologicalComplex.Hom.isoOfComponents
code: /-- Construct an isomorphism of chain complexes from isomorphism of the objects
which commute with the differentials. -/
@[simps]
def isoOfComponents (f : ∀ i, C₁.X i ≅ C₂.X i)
    (hf : ∀ i j, c.Rel i j → (f i).hom ≫ C₂.d i j = C₁.d i j ≫ (f j).hom := by aesop_cat) :
    C₁ ≅ C₂ 
goal: C₁ ≅ C₂

full_name: HomologicalComplex.Hom.isoOfComponents_inv_f
code: /-- Construct an isomorphism of chain complexes from isomorphism of the objects
which commute with the differentials. -/
@[simps]
def isoOfComponents (f : ∀ i, C₁.X i ≅ C₂.X i)
    (hf : ∀ i j, c.Rel i j → (f i).hom ≫ C₂.d i j = C₁.d i j ≫ (f j).hom := by aesop_cat) :
    C₁ ≅ C₂ 
goal: (HomologicalComplex.Hom.isoOfComponents f hf).inv.f i = (f i).inv

full_name: HomologicalComplex.Hom.isoOfComponents_app
code: @[simp]
theorem isoOfComponents_app (f : ∀ i, C₁.X i ≅ C₂.X i)
    (hf : ∀ i j, c.Rel i j → (f i).hom ≫ C₂.d i j = C₁.d i j ≫ (f j).hom) (i : ι) :
    isoApp (isoOfComponents f hf) i = f i 
goal: HomologicalComplex.Hom.isoApp (HomologicalComplex.Hom.isoOfComponents f hf) i = f i

full_name: HomologicalComplex.Hom.isIso_of_components
code: theorem isIso_of_components (f : C₁ ⟶ C₂) [∀ n : ι, IsIso (f.f n)] : IsIso f 
goal: CategoryTheory.IsIso f

full_name: HomologicalComplex.Hom.prev
code: /-- `f.prev j` is `f.f i` if there is some `r i j`, and `f.f j` otherwise. -/
abbrev prev (f : Hom C₁ C₂) (j : ι) : C₁.xPrev j ⟶ C₂.xPrev j 
goal: C₁.xPrev j ⟶ C₂.xPrev j

full_name: HomologicalComplex.Hom.prev_eq
code: theorem prev_eq (f : Hom C₁ C₂) {i j : ι} (w : c.Rel i j) :
    f.prev j = (C₁.xPrevIso w).hom ≫ f.f i ≫ (C₂.xPrevIso w).inv 
goal: f.prev j = (C₁.xPrevIso w).hom ≫ f.f i ≫ (C₂.xPrevIso w).inv

full_name: HomologicalComplex.Hom.next
code: /-- `f.next i` is `f.f j` if there is some `r i j`, and `f.f j` otherwise. -/
abbrev next (f : Hom C₁ C₂) (i : ι) : C₁.xNext i ⟶ C₂.xNext i 
goal: C₁.xNext i ⟶ C₂.xNext i

full_name: HomologicalComplex.Hom.next_eq
code: theorem next_eq (f : Hom C₁ C₂) {i j : ι} (w : c.Rel i j) :
    f.next i = (C₁.xNextIso w).hom ≫ f.f j ≫ (C₂.xNextIso w).inv 
goal: f.next i = (C₁.xNextIso w).hom ≫ f.f j ≫ (C₂.xNextIso w).inv

full_name: HomologicalComplex.Hom.comm_from
code: @[reassoc, elementwise] -- @[simp] -- Porting note (#10618): simp can prove this
theorem comm_from (f : Hom C₁ C₂) (i : ι) : f.f i ≫ C₂.dFrom i = C₁.dFrom i ≫ f.next i 
goal: f.f i ≫ C₂.dFrom i = C₁.dFrom i ≫ f.next i

full_name: HomologicalComplex.Hom.comm_to
code: @[reassoc, elementwise] -- @[simp] -- Porting note (#10618): simp can prove this
theorem comm_to (f : Hom C₁ C₂) (j : ι) : f.prev j ≫ C₂.dTo j = C₁.dTo j ≫ f.f j 
goal: f.prev j ≫ C₂.dTo j = C₁.dTo j ≫ f.f j

full_name: HomologicalComplex.Hom.sqFrom
code: /-- A morphism of chain complexes
induces a morphism of arrows of the differentials out of each object.
-/
def sqFrom (f : Hom C₁ C₂) (i : ι) : Arrow.mk (C₁.dFrom i) ⟶ Arrow.mk (C₂.dFrom i) 
goal: CategoryTheory.Arrow.mk (C₁.dFrom i) ⟶ CategoryTheory.Arrow.mk (C₂.dFrom i)

full_name: HomologicalComplex.Hom.sqFrom_left
code: @[simp]
theorem sqFrom_left (f : Hom C₁ C₂) (i : ι) : (f.sqFrom i).left = f.f i 
goal: (f.sqFrom i).left = f.f i

full_name: HomologicalComplex.Hom.sqFrom_right
code: @[simp]
theorem sqFrom_right (f : Hom C₁ C₂) (i : ι) : (f.sqFrom i).right = f.next i 
goal: (f.sqFrom i).right = f.next i

full_name: HomologicalComplex.Hom.sqFrom_id
code: @[simp]
theorem sqFrom_id (C₁ : HomologicalComplex V c) (i : ι) : sqFrom (𝟙 C₁) i = 𝟙 _ 
goal: HomologicalComplex.Hom.sqFrom (𝟙 C₁) i = 𝟙 (CategoryTheory.Arrow.mk (C₁.dFrom i))

full_name: HomologicalComplex.Hom.sqFrom_comp
code: @[simp]
theorem sqFrom_comp (f : C₁ ⟶ C₂) (g : C₂ ⟶ C₃) (i : ι) :
    sqFrom (f ≫ g) i = sqFrom f i ≫ sqFrom g i 
goal: HomologicalComplex.Hom.sqFrom (f ≫ g) i = HomologicalComplex.Hom.sqFrom f i ≫ HomologicalComplex.Hom.sqFrom g i

full_name: HomologicalComplex.Hom.sqTo
code: /-- A morphism of chain complexes
induces a morphism of arrows of the differentials into each object.
-/
def sqTo (f : Hom C₁ C₂) (j : ι) : Arrow.mk (C₁.dTo j) ⟶ Arrow.mk (C₂.dTo j) 
goal: CategoryTheory.Arrow.mk (C₁.dTo j) ⟶ CategoryTheory.Arrow.mk (C₂.dTo j)

full_name: HomologicalComplex.Hom.sqTo_left
code: @[simp]
theorem sqTo_left (f : Hom C₁ C₂) (j : ι) : (f.sqTo j).left = f.prev j 
goal: (f.sqTo j).left = f.prev j

full_name: HomologicalComplex.Hom.sqTo_right
code: @[simp]
theorem sqTo_right (f : Hom C₁ C₂) (j : ι) : (f.sqTo j).right = f.f j 
goal: (f.sqTo j).right = f.f j

full_name: ChainComplex.of
code: /-- Construct an `α`-indexed chain complex from a dependently-typed differential.
-/
def of (X : α → V) (d : ∀ n, X (n + 1) ⟶ X n) (sq : ∀ n, d (n + 1) ≫ d n = 0) : ChainComplex V α 
goal: ChainComplex V α

full_name: ChainComplex.of_x
code: @[simp]
theorem of_x (n : α) : (of X d sq).X n = X n 
goal: (ChainComplex.of X d sq).X n = X n

full_name: ChainComplex.of_d
code: @[simp]
theorem of_d (j : α) : (of X d sq).d (j + 1) j = d j 
goal: (ChainComplex.of X d sq).d (j + 1) j = d j

full_name: ChainComplex.of_d_ne
code: theorem of_d_ne {i j : α} (h : i ≠ j + 1) : (of X d sq).d i j = 0 
goal: (ChainComplex.of X d sq).d i j = 0

full_name: ChainComplex.ofHom_f
code: /-- A constructor for chain maps between `α`-indexed chain complexes built using `ChainComplex.of`,
from a dependently typed collection of morphisms.
-/
@[simps]
def ofHom (f : ∀ i : α, X i ⟶ Y i) (comm : ∀ i : α, f (i + 1) ≫ d_Y i = d_X i ≫ f i) :
    of X d_X sq_X ⟶ of Y d_Y sq_Y 
goal: (ChainComplex.ofHom X d_X sq_X Y d_Y sq_Y f comm).f i = f i

full_name: ChainComplex.ofHom
code: /-- A constructor for chain maps between `α`-indexed chain complexes built using `ChainComplex.of`,
from a dependently typed collection of morphisms.
-/
@[simps]
def ofHom (f : ∀ i : α, X i ⟶ Y i) (comm : ∀ i : α, f (i + 1) ≫ d_Y i = d_X i ≫ f i) :
    of X d_X sq_X ⟶ of Y d_Y sq_Y 
goal: ChainComplex.of X d_X sq_X ⟶ ChainComplex.of Y d_Y sq_Y

full_name: ChainComplex.mkAux
code: /-- Auxiliary definition for `mk`. -/
def mkAux : ℕ → ShortComplex V
  
goal: ℕ → CategoryTheory.ShortComplex V

full_name: ChainComplex.mk
code: /-- An inductive constructor for `ℕ`-indexed chain complexes.

You provide explicitly the first two differentials,
then a function which takes two differentials and the fact they compose to zero,
and returns the next object, its differential, and the fact it composes appropriately to zero.

See also `mk'`, which only sees the previous differential in the inductive step.
-/
def mk : ChainComplex V ℕ 
goal: ChainComplex V ℕ

full_name: ChainComplex.mk_X_0
code: @[simp]
theorem mk_X_0 : (mk X₀ X₁ X₂ d₀ d₁ s succ).X 0 = X₀ 
goal: (ChainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).X 0 = X₀

full_name: ChainComplex.mk_X_1
code: @[simp]
theorem mk_X_1 : (mk X₀ X₁ X₂ d₀ d₁ s succ).X 1 = X₁ 
goal: (ChainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).X 1 = X₁

full_name: ChainComplex.mk_X_2
code: @[simp]
theorem mk_X_2 : (mk X₀ X₁ X₂ d₀ d₁ s succ).X 2 = X₂ 
goal: (ChainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).X 2 = X₂

full_name: ChainComplex.mk_d_1_0
code: @[simp]
theorem mk_d_1_0 : (mk X₀ X₁ X₂ d₀ d₁ s succ).d 1 0 = d₀ 
goal: (ChainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).d 1 0 = d₀

full_name: ChainComplex.mk_d_2_1
code: @[simp]
theorem mk_d_2_1 : (mk X₀ X₁ X₂ d₀ d₁ s succ).d 2 1 = d₁ 
goal: (ChainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).d 2 1 = d₁

full_name: ChainComplex.mk'
code: /-- A simpler inductive constructor for `ℕ`-indexed chain complexes.

You provide explicitly the first differential,
then a function which takes a differential,
and returns the next object, its differential, and the fact it composes appropriately to zero.
-/
def mk' (X₀ X₁ : V) (d : X₁ ⟶ X₀)
    (succ' : ∀ {X₀ X₁ : V} (f : X₁ ⟶ X₀), Σ' (X₂ : V) (d : X₂ ⟶ X₁), d ≫ f = 0) :
    ChainComplex V ℕ 
goal: ChainComplex V ℕ

full_name: ChainComplex.mk'_X_0
code: @[simp]
theorem mk'_X_0 : (mk' X₀ X₁ d₀ succ').X 0 = X₀ 
goal: (ChainComplex.mk' X₀ X₁ d₀ fun {X₀ X₁} => succ').X 0 = X₀

full_name: ChainComplex.mk'_X_1
code: @[simp]
theorem mk'_X_1 : (mk' X₀ X₁ d₀ succ').X 1 = X₁ 
goal: (ChainComplex.mk' X₀ X₁ d₀ fun {X₀ X₁} => succ').X 1 = X₁

full_name: ChainComplex.mk'_d_1_0
code: @[simp]
theorem mk'_d_1_0 : (mk' X₀ X₁ d₀ succ').d 1 0 = d₀ 
goal: (ChainComplex.mk' X₀ X₁ d₀ fun {X₀ X₁} => succ').d 1 0 = d₀

full_name: ChainComplex.mkHomAux
code: /-- An auxiliary construction for `mkHom`.

Here we build by induction a family of commutative squares,
but don't require at the type level that these successive commutative squares actually agree.
They do in fact agree, and we then capture that at the type level (i.e. by constructing a chain map)
in `mkHom`.
-/
def mkHomAux :
    ∀ n,
      Σ' (f : P.X n ⟶ Q.X n) (f' : P.X (n + 1) ⟶ Q.X (n + 1)),
        f' ≫ Q.d (n + 1) n = P.d (n + 1) n ≫ f
  
goal: (f : P.X n ⟶ Q.X n) ×' (f' : P.X (n + 1) ⟶ Q.X (n + 1)) ×' f' ≫ Q.d (n + 1) n = P.d (n + 1) n ≫ f

full_name: ChainComplex.mkHom
code: /-- A constructor for chain maps between `ℕ`-indexed chain complexes,
working by induction on commutative squares.

You need to provide the components of the chain map in degrees 0 and 1,
show that these form a commutative square,
and then give a construction of each component,
and the fact that it forms a commutative square with the previous component,
using as an inductive hypothesis the data (and commutativity) of the previous two components.
-/
def mkHom : P ⟶ Q 
goal: P ⟶ Q

full_name: ChainComplex.mkHom_f_0
code: @[simp]
theorem mkHom_f_0 : (mkHom P Q zero one one_zero_comm succ).f 0 = zero 
goal: (P.mkHom Q zero one one_zero_comm succ).f 0 = zero

full_name: ChainComplex.mkHom_f_1
code: @[simp]
theorem mkHom_f_1 : (mkHom P Q zero one one_zero_comm succ).f 1 = one 
goal: (P.mkHom Q zero one one_zero_comm succ).f 1 = one

full_name: ChainComplex.mkHom_f_succ_succ
code: @[simp]
theorem mkHom_f_succ_succ (n : ℕ) :
    (mkHom P Q zero one one_zero_comm succ).f (n + 2) =
      (succ n
          ⟨(mkHom P Q zero one one_zero_comm succ).f n,
            (mkHom P Q zero one one_zero_comm succ).f (n + 1),
            (mkHom P Q zero one one_zero_comm succ).comm (n + 1) n⟩).1 
goal: (P.mkHom Q zero one one_zero_comm succ).f (n + 2) =
  (succ n ⟨(P.mkHom Q zero one one_zero_comm succ).f n, ⟨(P.mkHom Q zero one one_zero_comm succ).f (n + 1), ⋯⟩⟩).fst

full_name: CochainComplex.of
code: /-- Construct an `α`-indexed cochain complex from a dependently-typed differential.
-/
def of (X : α → V) (d : ∀ n, X n ⟶ X (n + 1)) (sq : ∀ n, d n ≫ d (n + 1) = 0) :
    CochainComplex V α 
goal: CochainComplex V α

full_name: CochainComplex.of_x
code: @[simp]
theorem of_x (n : α) : (of X d sq).X n = X n 
goal: (CochainComplex.of X d sq).X n = X n

full_name: CochainComplex.of_d
code: @[simp]
theorem of_d (j : α) : (of X d sq).d j (j + 1) = d j 
goal: (CochainComplex.of X d sq).d j (j + 1) = d j

full_name: CochainComplex.of_d_ne
code: theorem of_d_ne {i j : α} (h : i + 1 ≠ j) : (of X d sq).d i j = 0 
goal: (CochainComplex.of X d sq).d i j = 0

full_name: CochainComplex.ofHom
code: /--
A constructor for chain maps between `α`-indexed cochain complexes built using `CochainComplex.of`,
from a dependently typed collection of morphisms.
-/
@[simps]
def ofHom (f : ∀ i : α, X i ⟶ Y i) (comm : ∀ i : α, f i ≫ d_Y i = d_X i ≫ f (i + 1)) :
    of X d_X sq_X ⟶ of Y d_Y sq_Y 
goal: CochainComplex.of X d_X sq_X ⟶ CochainComplex.of Y d_Y sq_Y

full_name: CochainComplex.ofHom_f
code: /--
A constructor for chain maps between `α`-indexed cochain complexes built using `CochainComplex.of`,
from a dependently typed collection of morphisms.
-/
@[simps]
def ofHom (f : ∀ i : α, X i ⟶ Y i) (comm : ∀ i : α, f i ≫ d_Y i = d_X i ≫ f (i + 1)) :
    of X d_X sq_X ⟶ of Y d_Y sq_Y 
goal: (CochainComplex.ofHom X d_X sq_X Y d_Y sq_Y f comm).f i = f i

full_name: CochainComplex.mkAux
code: /-- Auxiliary definition for `mk`. -/
def mkAux : ℕ → ShortComplex V
  
goal: ℕ → CategoryTheory.ShortComplex V

full_name: CochainComplex.mk
code: /-- An inductive constructor for `ℕ`-indexed cochain complexes.

You provide explicitly the first two differentials,
then a function which takes two differentials and the fact they compose to zero,
and returns the next object, its differential, and the fact it composes appropriately to zero.

See also `mk'`, which only sees the previous differential in the inductive step.
-/
def mk : CochainComplex V ℕ 
goal: CochainComplex V ℕ

full_name: CochainComplex.mk_X_0
code: @[simp]
theorem mk_X_0 : (mk X₀ X₁ X₂ d₀ d₁ s succ).X 0 = X₀ 
goal: (CochainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).X 0 = X₀

full_name: CochainComplex.mk_X_1
code: @[simp]
theorem mk_X_1 : (mk X₀ X₁ X₂ d₀ d₁ s succ).X 1 = X₁ 
goal: (CochainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).X 1 = X₁

full_name: CochainComplex.mk_X_2
code: @[simp]
theorem mk_X_2 : (mk X₀ X₁ X₂ d₀ d₁ s succ).X 2 = X₂ 
goal: (CochainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).X 2 = X₂

full_name: CochainComplex.mk_d_1_0
code: @[simp]
theorem mk_d_1_0 : (mk X₀ X₁ X₂ d₀ d₁ s succ).d 0 1 = d₀ 
goal: (CochainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).d 0 1 = d₀

full_name: CochainComplex.mk_d_2_0
code: @[simp]
theorem mk_d_2_0 : (mk X₀ X₁ X₂ d₀ d₁ s succ).d 1 2 = d₁ 
goal: (CochainComplex.mk X₀ X₁ X₂ d₀ d₁ s succ).d 1 2 = d₁

full_name: CochainComplex.mk'
code: /-- A simpler inductive constructor for `ℕ`-indexed cochain complexes.

You provide explicitly the first differential,
then a function which takes a differential,
and returns the next object, its differential, and the fact it composes appropriately to zero.
-/
def mk' (X₀ X₁ : V) (d : X₀ ⟶ X₁)
    -- (succ' : ∀ : ΣX₀ X₁ : V, X₀ ⟶ X₁, Σ' (X₂ : V) (d : t.2.1 ⟶ X₂), t.2.2 ≫ d = 0) :
    (succ' : ∀ {X₀ X₁ : V} (f : X₀ ⟶ X₁), Σ' (X₂ : V) (d : X₁ ⟶ X₂), f ≫ d = 0) :
    CochainComplex V ℕ 
goal: CochainComplex V ℕ

full_name: CochainComplex.mk'_X_0
code: @[simp]
theorem mk'_X_0 : (mk' X₀ X₁ d₀ succ').X 0 = X₀ 
goal: (CochainComplex.mk' X₀ X₁ d₀ fun {X₀ X₁} => succ').X 0 = X₀

full_name: CochainComplex.mk'_X_1
code: @[simp]
theorem mk'_X_1 : (mk' X₀ X₁ d₀ succ').X 1 = X₁ 
goal: (CochainComplex.mk' X₀ X₁ d₀ fun {X₀ X₁} => succ').X 1 = X₁

full_name: CochainComplex.mk'_d_1_0
code: @[simp]
theorem mk'_d_1_0 : (mk' X₀ X₁ d₀ succ').d 0 1 = d₀ 
goal: (CochainComplex.mk' X₀ X₁ d₀ fun {X₀ X₁} => succ').d 0 1 = d₀

full_name: CochainComplex.mkHomAux
code: /-- An auxiliary construction for `mkHom`.

Here we build by induction a family of commutative squares,
but don't require at the type level that these successive commutative squares actually agree.
They do in fact agree, and we then capture that at the type level (i.e. by constructing a chain map)
in `mkHom`.
-/
def mkHomAux :
    ∀ n,
      Σ' (f : P.X n ⟶ Q.X n) (f' : P.X (n + 1) ⟶ Q.X (n + 1)),
        f ≫ Q.d n (n + 1) = P.d n (n + 1) ≫ f'
  
goal: (f : P.X n ⟶ Q.X n) ×' (f' : P.X (n + 1) ⟶ Q.X (n + 1)) ×' f ≫ Q.d n (n + 1) = P.d n (n + 1) ≫ f'

full_name: CochainComplex.mkHom
code: /-- A constructor for chain maps between `ℕ`-indexed cochain complexes,
working by induction on commutative squares.

You need to provide the components of the chain map in degrees 0 and 1,
show that these form a commutative square,
and then give a construction of each component,
and the fact that it forms a commutative square with the previous component,
using as an inductive hypothesis the data (and commutativity) of the previous two components.
-/
def mkHom : P ⟶ Q 
goal: P ⟶ Q

full_name: CochainComplex.mkHom_f_0
code: @[simp]
theorem mkHom_f_0 : (mkHom P Q zero one one_zero_comm succ).f 0 = zero 
goal: (P.mkHom Q zero one one_zero_comm succ).f 0 = zero

full_name: CochainComplex.mkHom_f_1
code: @[simp]
theorem mkHom_f_1 : (mkHom P Q zero one one_zero_comm succ).f 1 = one 
goal: (P.mkHom Q zero one one_zero_comm succ).f 1 = one

full_name: CochainComplex.mkHom_f_succ_succ
code: @[simp]
theorem mkHom_f_succ_succ (n : ℕ) :
    (mkHom P Q zero one one_zero_comm succ).f (n + 2) =
      (succ n
          ⟨(mkHom P Q zero one one_zero_comm succ).f n,
            (mkHom P Q zero one one_zero_comm succ).f (n + 1),
            (mkHom P Q zero one one_zero_comm succ).comm n (n + 1)⟩).1 
goal: (P.mkHom Q zero one one_zero_comm succ).f (n + 2) =
  (succ n ⟨(P.mkHom Q zero one one_zero_comm succ).f n, ⟨(P.mkHom Q zero one one_zero_comm succ).f (n + 1), ⋯⟩⟩).fst