l3lab/ntp-mathlib huggingface dataset:
/-- The right homology map data expressing that null homotopic maps induce the zero
morphism in right homology. -/
def RightHomologyMapData.ofNullHomotopic
    (H₁ : S₁.RightHomologyData) (H₂ : S₂.RightHomologyData)
    (h₀ : S₁.X₁ ⟶ S₂.X₁) (h₀_f : h₀ ≫ S₂.f = 0)
    (h₁ : S₁.X₂ ⟶ S₂.X₁) (h₂ : S₁.X₃ ⟶ S₂.X₂) (h₃ : S₁.X₃ ⟶ S₂.X₃) (g_h₃ : S₁.g ≫ h₃ = 0) :
    RightHomologyMapData (nullHomotopic _ _ h₀ h₀_f h₁ h₂ h₃ g_h₃) H₁ H₂ where
  φQ := H₁.descQ (S₁.g ≫ h₂ ≫ H₂.p) (by simp)
  φH := 0
  commg' := by
    

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.263845, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
H₁ : RightHomologyData S₁
H₂ : RightHomologyData S₂
h₀ : S₁.X₁ ⟶ S₂.X₁
h₀_f : h₀ ≫ S₂.f = 0
h₁ : S₁.X₂ ⟶ S₂.X₁
h₂ : S₁.X₃ ⟶ S₂.X₂
h₃ : S₁.X₃ ⟶ S₂.X₃
g_h₃ : S₁.g ≫ h₃ = 0
⊢ RightHomologyData.descQ H₁ (S₁.g ≫ h₂ ≫ H₂.p) (_ : S₁.f ≫ S₁.g ≫ h₂ ≫ H₂.p = 0) ≫ RightHomologyData.g' H₂ =
    RightHomologyData.g' H₁ ≫ (nullHomotopic S₁ S₂ h₀ h₀_f h₁ h₂ h₃ g_h₃).τ₃

Next tactic:
rw [← cancel_epi H₁.p, RightHomologyData.p_descQ_assoc, RightHomologyData.p_g'_assoc,
      nullHomotopic_τ₃, comp_add, assoc, assoc, RightHomologyData.p_g', g_h₃, add_zero]
/-- The right homology map data expressing that null homotopic maps induce the zero
morphism in right homology. -/
def RightHomologyMapData.ofNullHomotopic
    (H₁ : S₁.RightHomologyData) (H₂ : S₂.RightHomologyData)
    (h₀ : S₁.X₁ ⟶ S₂.X₁) (h₀_f : h₀ ≫ S₂.f = 0)
    (h₁ : S₁.X₂ ⟶ S₂.X₁) (h₂ : S₁.X₃ ⟶ S₂.X₂) (h₃ : S₁.X₃ ⟶ S₂.X₃) (g_h₃ : S₁.g ≫ h₃ = 0) :
    RightHomologyMapData (nullHomotopic _ _ h₀ h₀_f h₁ h₂ h₃ g_h₃) H₁ H₂ where
  φQ := H₁.descQ (S₁.g ≫ h₂ ≫ H₂.p) (by simp)
  φH := 0
  commg' := by
    rw [← cancel_epi H₁.p, RightHomologyData.p_descQ_assoc, RightHomologyData.p_g'_assoc,
      nullHomotopic_τ₃, comp_add, assoc, assoc, RightHomologyData.p_g', g_h₃, add_zero]
  commι := by
    

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.263845, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
H₁ : RightHomologyData S₁
H₂ : RightHomologyData S₂
h₀ : S₁.X₁ ⟶ S₂.X₁
h₀_f : h₀ ≫ S₂.f = 0
h₁ : S₁.X₂ ⟶ S₂.X₁
h₂ : S₁.X₃ ⟶ S₂.X₂
h₃ : S₁.X₃ ⟶ S₂.X₃
g_h₃ : S₁.g ≫ h₃ = 0
⊢ 0 ≫ H₂.ι = H₁.ι ≫ RightHomologyData.descQ H₁ (S₁.g ≫ h₂ ≫ H₂.p) (_ : S₁.f ≫ S₁.g ≫ h₂ ≫ H₂.p = 0)

Next tactic:
rw [H₁.ι_descQ_eq_zero_of_boundary (S₁.g ≫ h₂ ≫ H₂.p) (h₂ ≫ H₂.p) rfl, zero_comp]
@[simp]
lemma homologyMap'_nullHomotopic
    (H₁ : S₁.HomologyData) (H₂ : S₂.HomologyData)
    (h₀ : S₁.X₁ ⟶ S₂.X₁) (h₀_f : h₀ ≫ S₂.f = 0)
    (h₁ : S₁.X₂ ⟶ S₂.X₁) (h₂ : S₁.X₃ ⟶ S₂.X₂) (h₃ : S₁.X₃ ⟶ S₂.X₃) (g_h₃ : S₁.g ≫ h₃ = 0) :
    homologyMap' (nullHomotopic _ _ h₀ h₀_f h₁ h₂ h₃ g_h₃) H₁ H₂ = 0 :=
  by 

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
H₁ : HomologyData S₁
H₂ : HomologyData S₂
h₀ : S₁.X₁ ⟶ S₂.X₁
h₀_f : h₀ ≫ S₂.f = 0
h₁ : S₁.X₂ ⟶ S₂.X₁
h₂ : S₁.X₃ ⟶ S₂.X₂
h₃ : S₁.X₃ ⟶ S₂.X₃
g_h₃ : S₁.g ≫ h₃ = 0
⊢ homologyMap' (nullHomotopic S₁ S₂ h₀ h₀_f h₁ h₂ h₃ g_h₃) H₁ H₂ = 0

Next tactic:
apply leftHomologyMap'_nullHomotopic
@[simp]
lemma leftHomologyMap_nullHomotopic [S₁.HasLeftHomology] [S₂.HasLeftHomology]
    (h₀ : S₁.X₁ ⟶ S₂.X₁) (h₀_f : h₀ ≫ S₂.f = 0)
    (h₁ : S₁.X₂ ⟶ S₂.X₁) (h₂ : S₁.X₃ ⟶ S₂.X₂) (h₃ : S₁.X₃ ⟶ S₂.X₃) (g_h₃ : S₁.g ≫ h₃ = 0) :
    leftHomologyMap (nullHomotopic _ _ h₀ h₀_f h₁ h₂ h₃ g_h₃) = 0 :=
  by 

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
inst✝¹ : HasLeftHomology S₁
inst✝ : HasLeftHomology S₂
h₀ : S₁.X₁ ⟶ S₂.X₁
h₀_f : h₀ ≫ S₂.f = 0
h₁ : S₁.X₂ ⟶ S₂.X₁
h₂ : S₁.X₃ ⟶ S₂.X₂
h₃ : S₁.X₃ ⟶ S₂.X₃
g_h₃ : S₁.g ≫ h₃ = 0
⊢ leftHomologyMap (nullHomotopic S₁ S₂ h₀ h₀_f h₁ h₂ h₃ g_h₃) = 0

Next tactic:
apply leftHomologyMap'_nullHomotopic
@[simp]
lemma rightHomologyMap_nullHomotopic [S₁.HasRightHomology] [S₂.HasRightHomology]
    (h₀ : S₁.X₁ ⟶ S₂.X₁) (h₀_f : h₀ ≫ S₂.f = 0)
    (h₁ : S₁.X₂ ⟶ S₂.X₁) (h₂ : S₁.X₃ ⟶ S₂.X₂) (h₃ : S₁.X₃ ⟶ S₂.X₃) (g_h₃ : S₁.g ≫ h₃ = 0) :
    rightHomologyMap (nullHomotopic _ _ h₀ h₀_f h₁ h₂ h₃ g_h₃) = 0 :=
  by 

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
inst✝¹ : HasRightHomology S₁
inst✝ : HasRightHomology S₂
h₀ : S₁.X₁ ⟶ S₂.X₁
h₀_f : h₀ ≫ S₂.f = 0
h₁ : S₁.X₂ ⟶ S₂.X₁
h₂ : S₁.X₃ ⟶ S₂.X₂
h₃ : S₁.X₃ ⟶ S₂.X₃
g_h₃ : S₁.g ≫ h₃ = 0
⊢ rightHomologyMap (nullHomotopic S₁ S₂ h₀ h₀_f h₁ h₂ h₃ g_h₃) = 0

Next tactic:
apply rightHomologyMap'_nullHomotopic
@[simp]
lemma homologyMap_nullHomotopic [S₁.HasHomology] [S₂.HasHomology]
    (h₀ : S₁.X₁ ⟶ S₂.X₁) (h₀_f : h₀ ≫ S₂.f = 0)
    (h₁ : S₁.X₂ ⟶ S₂.X₁) (h₂ : S₁.X₃ ⟶ S₂.X₂) (h₃ : S₁.X₃ ⟶ S₂.X₃) (g_h₃ : S₁.g ≫ h₃ = 0) :
    homologyMap (nullHomotopic _ _ h₀ h₀_f h₁ h₂ h₃ g_h₃) = 0 :=
  by 

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
inst✝¹ : HasHomology S₁
inst✝ : HasHomology S₂
h₀ : S₁.X₁ ⟶ S₂.X₁
h₀_f : h₀ ≫ S₂.f = 0
h₁ : S₁.X₂ ⟶ S₂.X₁
h₂ : S₁.X₃ ⟶ S₂.X₂
h₃ : S₁.X₃ ⟶ S₂.X₃
g_h₃ : S₁.g ≫ h₃ = 0
⊢ homologyMap (nullHomotopic S₁ S₂ h₀ h₀_f h₁ h₂ h₃ g_h₃) = 0

Next tactic:
apply homologyMap'_nullHomotopic
lemma leftHomologyMap'_congr (h : Homotopy φ₁ φ₂) (h₁ : S₁.LeftHomologyData)
    (h₂ : S₂.LeftHomologyData) : leftHomologyMap' φ₁ h₁ h₂ = leftHomologyMap' φ₂ h₁ h₂ := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
h : Homotopy φ₁ φ₂
h₁ : LeftHomologyData S₁
h₂ : LeftHomologyData S₂
⊢ leftHomologyMap' φ₁ h₁ h₂ = leftHomologyMap' φ₂ h₁ h₂

Next tactic:
rw [h.eq_add_nullHomotopic, leftHomologyMap'_add, leftHomologyMap'_nullHomotopic, add_zero]
lemma rightHomologyMap'_congr (h : Homotopy φ₁ φ₂) (h₁ : S₁.RightHomologyData)
    (h₂ : S₂.RightHomologyData) : rightHomologyMap' φ₁ h₁ h₂ = rightHomologyMap' φ₂ h₁ h₂ := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
h : Homotopy φ₁ φ₂
h₁ : RightHomologyData S₁
h₂ : RightHomologyData S₂
⊢ rightHomologyMap' φ₁ h₁ h₂ = rightHomologyMap' φ₂ h₁ h₂

Next tactic:
rw [h.eq_add_nullHomotopic, rightHomologyMap'_add, rightHomologyMap'_nullHomotopic, add_zero]
lemma homologyMap'_congr (h : Homotopy φ₁ φ₂) (h₁ : S₁.HomologyData)
    (h₂ : S₂.HomologyData) : homologyMap' φ₁ h₁ h₂ = homologyMap' φ₂ h₁ h₂ := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
h : Homotopy φ₁ φ₂
h₁ : HomologyData S₁
h₂ : HomologyData S₂
⊢ homologyMap' φ₁ h₁ h₂ = homologyMap' φ₂ h₁ h₂

Next tactic:
rw [h.eq_add_nullHomotopic, homologyMap'_add, homologyMap'_nullHomotopic, add_zero]
/-- The homotopy equivalence from a short complex to itself that is induced
by the identity. -/
@[simps]
def refl (S : ShortComplex C) : HomotopyEquiv S S where
  hom := 𝟙 S
  inv := 𝟙 S
  homotopyHomInvId := Homotopy.ofEq (by 

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.290948, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
S : ShortComplex C
⊢ 𝟙 S ≫ 𝟙 S = 𝟙 S

Next tactic:
simp
/-- The homotopy equivalence from a short complex to itself that is induced
by the identity. -/
@[simps]
def refl (S : ShortComplex C) : HomotopyEquiv S S where
  hom := 𝟙 S
  inv := 𝟙 S
  homotopyHomInvId := Homotopy.ofEq (by simp)
  homotopyInvHomId := Homotopy.ofEq (by 

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.290948, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
S : ShortComplex C
⊢ 𝟙 S ≫ 𝟙 S = 𝟙 S

Next tactic:
simp
/-- The composition of homotopy equivalences. -/
@[simps]
def trans (e : HomotopyEquiv S₁ S₂) (e' : HomotopyEquiv S₂ S₃) :
    HomotopyEquiv S₁ S₃ where
  hom := e.hom ≫ e'.hom
  inv := e'.inv ≫ e.inv
  homotopyHomInvId := (Homotopy.ofEq (by 

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.293051, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
e : HomotopyEquiv S₁ S₂
e' : HomotopyEquiv S₂ S₃
⊢ (e.hom ≫ e'.hom) ≫ e'.inv ≫ e.inv = e.hom ≫ (e'.hom ≫ e'.inv) ≫ e.inv

Next tactic:
simp
/-- The composition of homotopy equivalences. -/
@[simps]
def trans (e : HomotopyEquiv S₁ S₂) (e' : HomotopyEquiv S₂ S₃) :
    HomotopyEquiv S₁ S₃ where
  hom := e.hom ≫ e'.hom
  inv := e'.inv ≫ e.inv
  homotopyHomInvId := (Homotopy.ofEq (by simp)).trans
    (((e'.homotopyHomInvId.compRight e.inv).compLeft e.hom).trans
      ((Homotopy.ofEq (by 

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.293051, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
e : HomotopyEquiv S₁ S₂
e' : HomotopyEquiv S₂ S₃
⊢ e.hom ≫ 𝟙 S₂ ≫ e.inv = e.hom ≫ e.inv

Next tactic:
simp
/-- The composition of homotopy equivalences. -/
@[simps]
def trans (e : HomotopyEquiv S₁ S₂) (e' : HomotopyEquiv S₂ S₃) :
    HomotopyEquiv S₁ S₃ where
  hom := e.hom ≫ e'.hom
  inv := e'.inv ≫ e.inv
  homotopyHomInvId := (Homotopy.ofEq (by simp)).trans
    (((e'.homotopyHomInvId.compRight e.inv).compLeft e.hom).trans
      ((Homotopy.ofEq (by simp)).trans e.homotopyHomInvId))
  homotopyInvHomId := (Homotopy.ofEq (by 

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.293051, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
e : HomotopyEquiv S₁ S₂
e' : HomotopyEquiv S₂ S₃
⊢ (e'.inv ≫ e.inv) ≫ e.hom ≫ e'.hom = e'.inv ≫ (e.inv ≫ e.hom) ≫ e'.hom

Next tactic:
simp
/-- The composition of homotopy equivalences. -/
@[simps]
def trans (e : HomotopyEquiv S₁ S₂) (e' : HomotopyEquiv S₂ S₃) :
    HomotopyEquiv S₁ S₃ where
  hom := e.hom ≫ e'.hom
  inv := e'.inv ≫ e.inv
  homotopyHomInvId := (Homotopy.ofEq (by simp)).trans
    (((e'.homotopyHomInvId.compRight e.inv).compLeft e.hom).trans
      ((Homotopy.ofEq (by simp)).trans e.homotopyHomInvId))
  homotopyInvHomId := (Homotopy.ofEq (by simp)).trans
    (((e.homotopyInvHomId.compRight e'.hom).compLeft e'.inv).trans
      ((Homotopy.ofEq (by 

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.293051, u_1} C
inst✝ : Preadditive C
S₁ S₂ S₃ : ShortComplex C
φ₁ φ₂ φ₃ φ₄ : S₁ ⟶ S₂
e : HomotopyEquiv S₁ S₂
e' : HomotopyEquiv S₂ S₃
⊢ e'.inv ≫ 𝟙 S₂ ≫ e'.hom = e'.inv ≫ e'.hom

Next tactic:
simp
instance funLike : FunLike (MulChar R R') R (fun _ => R') :=
  ⟨fun χ => χ.toFun,
    fun χ₀ χ₁ h => by 

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ₀ χ₁ : MulChar R R'
h : (fun χ => χ.toFun) χ₀ = (fun χ => χ.toFun) χ₁
⊢ χ₀ = χ₁

Next tactic:
cases χ₀
instance funLike : FunLike (MulChar R R') R (fun _ => R') :=
  ⟨fun χ => χ.toFun,
    fun χ₀ χ₁ h => by cases χ₀; 

Proof state:
case mk
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ₁ : MulChar R R'
toMonoidHom✝ : R →* R'
map_nonunit'✝ : ∀ (a : R), ¬IsUnit a → OneHom.toFun (↑toMonoidHom✝) a = 0
h : (fun χ => χ.toFun) { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ } = (fun χ => χ.toFun) χ₁
⊢ { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ } = χ₁

Next tactic:
cases χ₁
instance funLike : FunLike (MulChar R R') R (fun _ => R') :=
  ⟨fun χ => χ.toFun,
    fun χ₀ χ₁ h => by cases χ₀; cases χ₁; 

Proof state:
case mk.mk
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
toMonoidHom✝¹ : R →* R'
map_nonunit'✝¹ : ∀ (a : R), ¬IsUnit a → OneHom.toFun (↑toMonoidHom✝¹) a = 0
toMonoidHom✝ : R →* R'
map_nonunit'✝ : ∀ (a : R), ¬IsUnit a → OneHom.toFun (↑toMonoidHom✝) a = 0
h :
  (fun χ => χ.toFun) { toMonoidHom := toMonoidHom✝¹, map_nonunit' := map_nonunit'✝¹ } =
    (fun χ => χ.toFun) { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ }
⊢ { toMonoidHom := toMonoidHom✝¹, map_nonunit' := map_nonunit'✝¹ } =
    { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ }

Next tactic:
congr
instance funLike : FunLike (MulChar R R') R (fun _ => R') :=
  ⟨fun χ => χ.toFun,
    fun χ₀ χ₁ h => by cases χ₀; cases χ₁; congr; 

Proof state:
case mk.mk.e_toMonoidHom
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
toMonoidHom✝¹ : R →* R'
map_nonunit'✝¹ : ∀ (a : R), ¬IsUnit a → OneHom.toFun (↑toMonoidHom✝¹) a = 0
toMonoidHom✝ : R →* R'
map_nonunit'✝ : ∀ (a : R), ¬IsUnit a → OneHom.toFun (↑toMonoidHom✝) a = 0
h :
  (fun χ => χ.toFun) { toMonoidHom := toMonoidHom✝¹, map_nonunit' := map_nonunit'✝¹ } =
    (fun χ => χ.toFun) { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ }
⊢ toMonoidHom✝¹ = toMonoidHom✝

Next tactic:
apply MonoidHom.ext (fun _ => congr_fun h _)
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by 

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
⊢ R → R'

Next tactic:
classical exact fun x => if IsUnit x then 1 else 0
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical 

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
⊢ R → R'

Next tactic:
exact fun x => if IsUnit x then 1 else 0
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by 

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
⊢ (if IsUnit 1 then 1 else 0) = 1

Next tactic:
simp only [isUnit_one, if_true]
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
⊢ ∀ (x y : R),
    OneHom.toFun { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
        (x * y) =
      OneHom.toFun { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
          x *
        OneHom.toFun { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
          y

Next tactic:
intro x y
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    intro x y
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
x y : R
⊢ OneHom.toFun { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
      (x * y) =
    OneHom.toFun { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) } x *
      OneHom.toFun { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) } y

Next tactic:
classical
      simp only [IsUnit.mul_iff, boole_mul]
      split_ifs <;> tauto
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    intro x y
    classical
      

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
x y : R
⊢ OneHom.toFun { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
      (x * y) =
    OneHom.toFun { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) } x *
      OneHom.toFun { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) } y

Next tactic:
simp only [IsUnit.mul_iff, boole_mul]
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    intro x y
    classical
      simp only [IsUnit.mul_iff, boole_mul]
      

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
x y : R
⊢ (if IsUnit x ∧ IsUnit y then 1 else 0) = if IsUnit x then if IsUnit y then 1 else 0 else 0

Next tactic:
split_ifs
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    intro x y
    classical
      simp only [IsUnit.mul_iff, boole_mul]
      split_ifs <;> 

Proof state:
case pos
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
x y : R
h✝² : IsUnit x ∧ IsUnit y
h✝¹ : IsUnit x
h✝ : IsUnit y
⊢ 1 = 1

Next tactic:
tauto
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    intro x y
    classical
      simp only [IsUnit.mul_iff, boole_mul]
      split_ifs <;> 

Proof state:
case neg
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
x y : R
h✝² : IsUnit x ∧ IsUnit y
h✝¹ : IsUnit x
h✝ : ¬IsUnit y
⊢ 1 = 0

Next tactic:
tauto
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    intro x y
    classical
      simp only [IsUnit.mul_iff, boole_mul]
      split_ifs <;> 

Proof state:
case neg
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
x y : R
h✝¹ : IsUnit x ∧ IsUnit y
h✝ : ¬IsUnit x
⊢ 1 = 0

Next tactic:
tauto
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    intro x y
    classical
      simp only [IsUnit.mul_iff, boole_mul]
      split_ifs <;> 

Proof state:
case pos
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
x y : R
h✝² : ¬(IsUnit x ∧ IsUnit y)
h✝¹ : IsUnit x
h✝ : IsUnit y
⊢ 0 = 1

Next tactic:
tauto
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    intro x y
    classical
      simp only [IsUnit.mul_iff, boole_mul]
      split_ifs <;> 

Proof state:
case neg
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
x y : R
h✝² : ¬(IsUnit x ∧ IsUnit y)
h✝¹ : IsUnit x
h✝ : ¬IsUnit y
⊢ 0 = 0

Next tactic:
tauto
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    simp only [ha, if_false]
  map_one' := by simp only [isUnit_one, if_true]
  map_mul' := by
    intro x y
    classical
      simp only [IsUnit.mul_iff, boole_mul]
      split_ifs <;> 

Proof state:
case neg
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
x y : R
h✝¹ : ¬(IsUnit x ∧ IsUnit y)
h✝ : ¬IsUnit x
⊢ 0 = 0

Next tactic:
tauto
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
⊢ ∀ (a : R),
    ¬IsUnit a →
      OneHom.toFun
          (↑{
              toOneHom :=
                { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) },
              map_mul' :=
                (_ :
                  ∀ (x y : R),
                    OneHom.toFun
                        { toFun := fun x => if IsUnit x then 1 else 0,
                          map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
                        (x * y) =
                      OneHom.toFun
                          { toFun := fun x => if IsUnit x then 1 else 0,
                            map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
                          x *
                        OneHom.toFun
                          { toFun := fun x => if IsUnit x then 1 else 0,
                            map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
                          y) })
          a =
        0

Next tactic:
intro a ha
/-- The trivial multiplicative character. It takes the value `0` on non-units and
the value `1` on units. -/
@[simps]
noncomputable def trivial : MulChar R R' where
  toFun := by classical exact fun x => if IsUnit x then 1 else 0
  map_nonunit' := by
    intro a ha
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
a : R
ha : ¬IsUnit a
⊢ OneHom.toFun
      (↑{
          toOneHom :=
            { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) },
          map_mul' :=
            (_ :
              ∀ (x y : R),
                OneHom.toFun
                    { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
                    (x * y) =
                  OneHom.toFun
                      { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
                      x *
                    OneHom.toFun
                      { toFun := fun x => if IsUnit x then 1 else 0, map_one' := (_ : (if IsUnit 1 then 1 else 0) = 1) }
                      y) })
      a =
    0

Next tactic:
simp only [ha, if_false]
/-- Extensionality. See `ext` below for the version that will actually be used. -/
theorem ext' {χ χ' : MulChar R R'} (h : ∀ a, χ a = χ' a) : χ = χ' := by
  

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ χ' : MulChar R R'
h : ∀ (a : R), χ a = χ' a
⊢ χ = χ'

Next tactic:
cases χ
/-- Extensionality. See `ext` below for the version that will actually be used. -/
theorem ext' {χ χ' : MulChar R R'} (h : ∀ a, χ a = χ' a) : χ = χ' := by
  cases χ
  

Proof state:
case mk
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ' : MulChar R R'
toMonoidHom✝ : R →* R'
map_nonunit'✝ : ∀ (a : R), ¬IsUnit a → OneHom.toFun (↑toMonoidHom✝) a = 0
h : ∀ (a : R), { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ } a = χ' a
⊢ { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ } = χ'

Next tactic:
cases χ'