l3lab/ntp-mathlib huggingface dataset:
/-- Taking injective resolutions is functorial,
if considered with target the homotopy category
(`ℕ`-indexed cochain complexes and chain maps up to homotopy).
-/
def injectiveResolutions : C ⥤ HomotopyCategory C (ComplexShape.up ℕ) where
  obj X := (HomotopyCategory.quotient _ _).obj (injectiveResolution X).cocomplex
  map f := (HomotopyCategory.quotient _ _).map (InjectiveResolution.desc f _ _)
  map_id X := by
    rw [← (HomotopyCategory.quotient _ _).map_id]
    apply HomotopyCategory.eq_of_homotopy
    apply InjectiveResolution.descIdHomotopy
  map_comp f g := by
    

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X✝ Y✝ Z✝ : C
f : X✝ ⟶ Y✝
g : Y✝ ⟶ Z✝
⊢ { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X).cocomplex,
          map := fun {X Y} f =>
            (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map
              (InjectiveResolution.desc f (injectiveResolution Y) (injectiveResolution X)) }.map
      (f ≫ g) =
    { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X).cocomplex,
            map := fun {X Y} f =>
              (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map
                (InjectiveResolution.desc f (injectiveResolution Y) (injectiveResolution X)) }.map
        f ≫
      { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X).cocomplex,
            map := fun {X Y} f =>
              (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map
                (InjectiveResolution.desc f (injectiveResolution Y) (injectiveResolution X)) }.map
        g

Next tactic:
rw [← (HomotopyCategory.quotient _ _).map_comp]
/-- Taking injective resolutions is functorial,
if considered with target the homotopy category
(`ℕ`-indexed cochain complexes and chain maps up to homotopy).
-/
def injectiveResolutions : C ⥤ HomotopyCategory C (ComplexShape.up ℕ) where
  obj X := (HomotopyCategory.quotient _ _).obj (injectiveResolution X).cocomplex
  map f := (HomotopyCategory.quotient _ _).map (InjectiveResolution.desc f _ _)
  map_id X := by
    rw [← (HomotopyCategory.quotient _ _).map_id]
    apply HomotopyCategory.eq_of_homotopy
    apply InjectiveResolution.descIdHomotopy
  map_comp f g := by
    rw [← (HomotopyCategory.quotient _ _).map_comp]
    

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X✝ Y✝ Z✝ : C
f : X✝ ⟶ Y✝
g : Y✝ ⟶ Z✝
⊢ { obj := fun X => (HomotopyCategory.quotient C (ComplexShape.up ℕ)).obj (injectiveResolution X).cocomplex,
          map := fun {X Y} f =>
            (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map
              (InjectiveResolution.desc f (injectiveResolution Y) (injectiveResolution X)) }.map
      (f ≫ g) =
    (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map
      (InjectiveResolution.desc f (injectiveResolution Y✝) (injectiveResolution X✝) ≫
        InjectiveResolution.desc g (injectiveResolution Z✝) (injectiveResolution Y✝))

Next tactic:
apply HomotopyCategory.eq_of_homotopy
/-- Taking injective resolutions is functorial,
if considered with target the homotopy category
(`ℕ`-indexed cochain complexes and chain maps up to homotopy).
-/
def injectiveResolutions : C ⥤ HomotopyCategory C (ComplexShape.up ℕ) where
  obj X := (HomotopyCategory.quotient _ _).obj (injectiveResolution X).cocomplex
  map f := (HomotopyCategory.quotient _ _).map (InjectiveResolution.desc f _ _)
  map_id X := by
    rw [← (HomotopyCategory.quotient _ _).map_id]
    apply HomotopyCategory.eq_of_homotopy
    apply InjectiveResolution.descIdHomotopy
  map_comp f g := by
    rw [← (HomotopyCategory.quotient _ _).map_comp]
    apply HomotopyCategory.eq_of_homotopy
    

Proof state:
case h
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X✝ Y✝ Z✝ : C
f : X✝ ⟶ Y✝
g : Y✝ ⟶ Z✝
⊢ Homotopy (InjectiveResolution.desc (f ≫ g) (injectiveResolution Z✝) (injectiveResolution X✝))
    (InjectiveResolution.desc f (injectiveResolution Y✝) (injectiveResolution X✝) ≫
      InjectiveResolution.desc g (injectiveResolution Z✝) (injectiveResolution Y✝))

Next tactic:
apply InjectiveResolution.descCompHomotopy
@[reassoc]
lemma InjectiveResolution.iso_hom_naturality {X Y : C} (f : X ⟶ Y)
    (I : InjectiveResolution X) (J : InjectiveResolution Y)
    (φ : I.cocomplex ⟶ J.cocomplex) (comm : I.ι.f 0 ≫ φ.f 0 = f ≫ J.ι.f 0) :
    (injectiveResolutions C).map f ≫ J.iso.hom =
      I.iso.hom ≫ (HomotopyCategory.quotient _ _).map φ := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X Y : C
f : X ⟶ Y
I : InjectiveResolution X
J : InjectiveResolution Y
φ : I.cocomplex ⟶ J.cocomplex
comm : HomologicalComplex.Hom.f I.ι 0 ≫ HomologicalComplex.Hom.f φ 0 = f ≫ HomologicalComplex.Hom.f J.ι 0
⊢ (injectiveResolutions C).map f ≫ (iso J).hom = (iso I).hom ≫ (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map φ

Next tactic:
apply HomotopyCategory.eq_of_homotopy
@[reassoc]
lemma InjectiveResolution.iso_hom_naturality {X Y : C} (f : X ⟶ Y)
    (I : InjectiveResolution X) (J : InjectiveResolution Y)
    (φ : I.cocomplex ⟶ J.cocomplex) (comm : I.ι.f 0 ≫ φ.f 0 = f ≫ J.ι.f 0) :
    (injectiveResolutions C).map f ≫ J.iso.hom =
      I.iso.hom ≫ (HomotopyCategory.quotient _ _).map φ := by
  apply HomotopyCategory.eq_of_homotopy
  

Proof state:
case h
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X Y : C
f : X ⟶ Y
I : InjectiveResolution X
J : InjectiveResolution Y
φ : I.cocomplex ⟶ J.cocomplex
comm : HomologicalComplex.Hom.f I.ι 0 ≫ HomologicalComplex.Hom.f φ 0 = f ≫ HomologicalComplex.Hom.f J.ι 0
⊢ Homotopy (desc f (injectiveResolution Y) (injectiveResolution X) ≫ (homotopyEquiv (injectiveResolution Y) J).hom)
    ((homotopyEquiv (injectiveResolution X) I).hom ≫ φ)

Next tactic:
apply descHomotopy f
@[reassoc]
lemma InjectiveResolution.iso_hom_naturality {X Y : C} (f : X ⟶ Y)
    (I : InjectiveResolution X) (J : InjectiveResolution Y)
    (φ : I.cocomplex ⟶ J.cocomplex) (comm : I.ι.f 0 ≫ φ.f 0 = f ≫ J.ι.f 0) :
    (injectiveResolutions C).map f ≫ J.iso.hom =
      I.iso.hom ≫ (HomotopyCategory.quotient _ _).map φ := by
  apply HomotopyCategory.eq_of_homotopy
  apply descHomotopy f
  

Proof state:
case h.g_comm
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X Y : C
f : X ⟶ Y
I : InjectiveResolution X
J : InjectiveResolution Y
φ : I.cocomplex ⟶ J.cocomplex
comm : HomologicalComplex.Hom.f I.ι 0 ≫ HomologicalComplex.Hom.f φ 0 = f ≫ HomologicalComplex.Hom.f J.ι 0
⊢ (injectiveResolution X).ι ≫
      desc f (injectiveResolution Y) (injectiveResolution X) ≫ (homotopyEquiv (injectiveResolution Y) J).hom =
    (CochainComplex.single₀ C).map f ≫ J.ι
case h.h_comm
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X Y : C
f : X ⟶ Y
I : InjectiveResolution X
J : InjectiveResolution Y
φ : I.cocomplex ⟶ J.cocomplex
comm : HomologicalComplex.Hom.f I.ι 0 ≫ HomologicalComplex.Hom.f φ 0 = f ≫ HomologicalComplex.Hom.f J.ι 0
⊢ (injectiveResolution X).ι ≫ (homotopyEquiv (injectiveResolution X) I).hom ≫ φ = (CochainComplex.single₀ C).map f ≫ J.ι

Next tactic:
all_goals aesop_cat
@[reassoc]
lemma InjectiveResolution.iso_hom_naturality {X Y : C} (f : X ⟶ Y)
    (I : InjectiveResolution X) (J : InjectiveResolution Y)
    (φ : I.cocomplex ⟶ J.cocomplex) (comm : I.ι.f 0 ≫ φ.f 0 = f ≫ J.ι.f 0) :
    (injectiveResolutions C).map f ≫ J.iso.hom =
      I.iso.hom ≫ (HomotopyCategory.quotient _ _).map φ := by
  apply HomotopyCategory.eq_of_homotopy
  apply descHomotopy f
  all_goals 

Proof state:
case h.g_comm
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X Y : C
f : X ⟶ Y
I : InjectiveResolution X
J : InjectiveResolution Y
φ : I.cocomplex ⟶ J.cocomplex
comm : HomologicalComplex.Hom.f I.ι 0 ≫ HomologicalComplex.Hom.f φ 0 = f ≫ HomologicalComplex.Hom.f J.ι 0
⊢ (injectiveResolution X).ι ≫
      desc f (injectiveResolution Y) (injectiveResolution X) ≫ (homotopyEquiv (injectiveResolution Y) J).hom =
    (CochainComplex.single₀ C).map f ≫ J.ι

Next tactic:
aesop_cat
@[reassoc]
lemma InjectiveResolution.iso_hom_naturality {X Y : C} (f : X ⟶ Y)
    (I : InjectiveResolution X) (J : InjectiveResolution Y)
    (φ : I.cocomplex ⟶ J.cocomplex) (comm : I.ι.f 0 ≫ φ.f 0 = f ≫ J.ι.f 0) :
    (injectiveResolutions C).map f ≫ J.iso.hom =
      I.iso.hom ≫ (HomotopyCategory.quotient _ _).map φ := by
  apply HomotopyCategory.eq_of_homotopy
  apply descHomotopy f
  all_goals 

Proof state:
case h.h_comm
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X Y : C
f : X ⟶ Y
I : InjectiveResolution X
J : InjectiveResolution Y
φ : I.cocomplex ⟶ J.cocomplex
comm : HomologicalComplex.Hom.f I.ι 0 ≫ HomologicalComplex.Hom.f φ 0 = f ≫ HomologicalComplex.Hom.f J.ι 0
⊢ (injectiveResolution X).ι ≫ (homotopyEquiv (injectiveResolution X) I).hom ≫ φ = (CochainComplex.single₀ C).map f ≫ J.ι

Next tactic:
aesop_cat
@[reassoc]
lemma InjectiveResolution.iso_inv_naturality {X Y : C} (f : X ⟶ Y)
    (I : InjectiveResolution X) (J : InjectiveResolution Y)
    (φ : I.cocomplex ⟶ J.cocomplex) (comm : I.ι.f 0 ≫ φ.f 0 = f ≫ J.ι.f 0) :
    I.iso.inv ≫ (injectiveResolutions C).map f =
      (HomotopyCategory.quotient _ _).map φ ≫ J.iso.inv := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : HasInjectiveResolutions C
X Y : C
f : X ⟶ Y
I : InjectiveResolution X
J : InjectiveResolution Y
φ : I.cocomplex ⟶ J.cocomplex
comm : HomologicalComplex.Hom.f I.ι 0 ≫ HomologicalComplex.Hom.f φ 0 = f ≫ HomologicalComplex.Hom.f J.ι 0
⊢ (iso I).inv ≫ (injectiveResolutions C).map f = (HomotopyCategory.quotient C (ComplexShape.up ℕ)).map φ ≫ (iso J).inv

Next tactic:
rw [← cancel_mono (J.iso).hom, Category.assoc, iso_hom_naturality f I J φ comm,
    Iso.inv_hom_id_assoc, Category.assoc, Iso.inv_hom_id, Category.comp_id]
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
⊢ f ≫ d f = 0

Next tactic:
simp
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
⊢ ShortComplex.Exact (ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0))

Next tactic:
let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
⊢ f ≫ cokernel.π f = 0

Next tactic:
simp
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
⊢ f ≫ d f = 0

Next tactic:
simp
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
⊢ ShortComplex.Exact (ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0))

Next tactic:
have : Epi α.τ₁ := by dsimp; infer_instance
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
⊢ Epi α.τ₁

Next tactic:
dsimp
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
⊢ Epi (𝟙 X)

Next tactic:
infer_instance
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; infer_instance
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
this : Epi α.τ₁
⊢ ShortComplex.Exact (ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0))

Next tactic:
have : IsIso α.τ₂ := by dsimp; infer_instance
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; infer_instance
  have : IsIso α.τ₂ := by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
this : Epi α.τ₁
⊢ IsIso α.τ₂

Next tactic:
dsimp
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; infer_instance
  have : IsIso α.τ₂ := by dsimp; 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
this : Epi α.τ₁
⊢ IsIso (𝟙 Y)

Next tactic:
infer_instance
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; infer_instance
  have : IsIso α.τ₂ := by dsimp; infer_instance
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
this✝ : Epi α.τ₁
this : IsIso α.τ₂
⊢ ShortComplex.Exact (ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0))

Next tactic:
have : Mono α.τ₃ := by dsimp; infer_instance
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; infer_instance
  have : IsIso α.τ₂ := by dsimp; infer_instance
  have : Mono α.τ₃ := by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
this✝ : Epi α.τ₁
this : IsIso α.τ₂
⊢ Mono α.τ₃

Next tactic:
dsimp
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; infer_instance
  have : IsIso α.τ₂ := by dsimp; infer_instance
  have : Mono α.τ₃ := by dsimp; 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
this✝ : Epi α.τ₁
this : IsIso α.τ₂
⊢ Mono (ι (cokernel f))

Next tactic:
infer_instance
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; infer_instance
  have : IsIso α.τ₂ := by dsimp; infer_instance
  have : Mono α.τ₃ := by dsimp; infer_instance
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
this✝¹ : Epi α.τ₁
this✝ : IsIso α.τ₂
this : Mono α.τ₃
⊢ ShortComplex.Exact (ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0))

Next tactic:
rw [← ShortComplex.exact_iff_of_epi_of_isIso_of_mono α]
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; infer_instance
  have : IsIso α.τ₂ := by dsimp; infer_instance
  have : Mono α.τ₃ := by dsimp; infer_instance
  rw [← ShortComplex.exact_iff_of_epi_of_isIso_of_mono α]
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
this✝¹ : Epi α.τ₁
this✝ : IsIso α.τ₂
this : Mono α.τ₃
⊢ ShortComplex.Exact (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0))

Next tactic:
apply ShortComplex.exact_of_g_is_cokernel
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
    (ShortComplex.mk f (d f) (by simp)).Exact := by
  let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
    { τ₁ := 𝟙 _
      τ₂ := 𝟙 _
      τ₃ := Injective.ι _  }
  have : Epi α.τ₁ := by dsimp; infer_instance
  have : IsIso α.τ₂ := by dsimp; infer_instance
  have : Mono α.τ₃ := by dsimp; infer_instance
  rw [← ShortComplex.exact_iff_of_epi_of_isIso_of_mono α]
  apply ShortComplex.exact_of_g_is_cokernel
  

Proof state:
case hS
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
X Y : C
f : X ⟶ Y
α : ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0) ⟶
  ShortComplex.mk f (d f) (_ : f ≫ cokernel.π f ≫ ι (cokernel f) = 0) :=
  ShortComplex.Hom.mk (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₁)
    (𝟙 (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₂)
    (ι (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).X₃)
this✝¹ : Epi α.τ₁
this✝ : IsIso α.τ₂
this : Mono α.τ₃
⊢ IsColimit
    (CokernelCofork.ofπ (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).g
      (_ :
        (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).f ≫
            (ShortComplex.mk f (cokernel.π f) (_ : f ≫ cokernel.π f = 0)).g =
          0))

Next tactic:
apply cokernelIsCokernel
/-- Auxiliary definition for `InjectiveResolution.of`. -/
def ofCocomplex : CochainComplex C ℕ :=
  CochainComplex.mk' (Injective.under Z) (Injective.syzygies (Injective.ι Z))
    (Injective.d (Injective.ι Z)) fun ⟨_, _, f⟩ =>
    ⟨Injective.syzygies f, Injective.d f, by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
x✝ : (X₀ : C) × (X₁ : C) × (X₀ ⟶ X₁)
fst✝¹ fst✝ : C
f : fst✝¹ ⟶ fst✝
⊢ { fst := fst✝¹, snd := { fst := fst✝, snd := f } }.snd.snd ≫ d f = 0

Next tactic:
simp
lemma ofCocomplex_d_0_1 :
    (ofCocomplex Z).d 0 1 = d (Injective.ι Z) := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
⊢ HomologicalComplex.d (ofCocomplex Z) 0 1 = d (Injective.ι Z)

Next tactic:
simp [ofCocomplex]
lemma ofCocomplex_exactAt_succ (n : ℕ) :
    (ofCocomplex Z).ExactAt (n + 1) := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Abelian C
inst✝ : EnoughInjectives C
Z : C
n : ℕ
⊢ HomologicalComplex.ExactAt (ofCocomplex Z) (n + 1)

Next tactic:
rw [HomologicalComplex.exactAt_iff' _ n (n + 1) (n + 1 + 1) (by simp) (by simp)]