l3lab/ntp-mathlib huggingface dataset:
/-- Extensionality. See `ext` below for the version that will actually be used. -/
theorem ext' {χ χ' : MulChar R R'} (h : ∀ a, χ a = χ' a) : χ = χ' := 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 :
  ∀ (a : R),
    { toMonoidHom := toMonoidHom✝¹, map_nonunit' := map_nonunit'✝¹ } a =
      { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ } a
⊢ { toMonoidHom := toMonoidHom✝¹, map_nonunit' := map_nonunit'✝¹ } =
    { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ }

Next tactic:
congr
/-- Extensionality. See `ext` below for the version that will actually be used. -/
theorem ext' {χ χ' : MulChar R R'} (h : ∀ a, χ a = χ' a) : χ = χ' := 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 :
  ∀ (a : R),
    { toMonoidHom := toMonoidHom✝¹, map_nonunit' := map_nonunit'✝¹ } a =
      { toMonoidHom := toMonoidHom✝, map_nonunit' := map_nonunit'✝ } a
⊢ toMonoidHom✝¹ = toMonoidHom✝

Next tactic:
exact MonoidHom.ext h
/-- Extensionality. Since `MulChar`s always take the value zero on non-units, it is sufficient
to compare the values on units. -/
@[ext]
theorem ext {χ χ' : MulChar R R'} (h : ∀ a : Rˣ, χ 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:
apply ext'
/-- Extensionality. Since `MulChar`s always take the value zero on non-units, it is sufficient
to compare the values on units. -/
@[ext]
theorem ext {χ χ' : MulChar R R'} (h : ∀ a : Rˣ, χ a = χ' a) : χ = χ' := by
  apply ext'
  

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

Next tactic:
intro a
/-- Extensionality. Since `MulChar`s always take the value zero on non-units, it is sufficient
to compare the values on units. -/
@[ext]
theorem ext {χ χ' : MulChar R R'} (h : ∀ a : Rˣ, χ a = χ' a) : χ = χ' := by
  apply ext'
  intro a
  

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

Next tactic:
by_cases ha : IsUnit a
/-- Extensionality. Since `MulChar`s always take the value zero on non-units, it is sufficient
to compare the values on units. -/
@[ext]
theorem ext {χ χ' : MulChar R R'} (h : ∀ a : Rˣ, χ a = χ' a) : χ = χ' := by
  apply ext'
  intro a
  by_cases ha : IsUnit a
  · 

Proof state:
case pos
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ χ' : MulChar R R'
h : ∀ (a : Rˣ), χ ↑a = χ' ↑a
a : R
ha : IsUnit a
⊢ χ a = χ' a

Next tactic:
exact h ha.unit
/-- Extensionality. Since `MulChar`s always take the value zero on non-units, it is sufficient
to compare the values on units. -/
@[ext]
theorem ext {χ χ' : MulChar R R'} (h : ∀ a : Rˣ, χ a = χ' a) : χ = χ' := by
  apply ext'
  intro a
  by_cases ha : IsUnit a
  · exact h ha.unit
  · 

Proof state:
case neg
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ χ' : MulChar R R'
h : ∀ (a : Rˣ), χ ↑a = χ' ↑a
a : R
ha : ¬IsUnit a
⊢ χ a = χ' a

Next tactic:
rw [map_nonunit χ ha, map_nonunit χ' ha]
theorem ext_iff {χ χ' : MulChar R R'} : χ = χ' ↔ ∀ a : Rˣ, χ a = χ' a :=
  ⟨by
    

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

Next tactic:
rintro rfl a
theorem ext_iff {χ χ' : MulChar R R'} : χ = χ' ↔ ∀ a : Rˣ, χ a = χ' a :=
  ⟨by
    rintro rfl a
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
a : Rˣ
⊢ χ ↑a = χ ↑a

Next tactic:
rfl
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by 

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

Next tactic:
classical exact fun x => if hx : IsUnit x then f hx.unit else 0
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical 

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

Next tactic:
exact fun x => if hx : IsUnit x then f hx.unit else 0
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
⊢ (if hx : IsUnit 1 then ↑(f (IsUnit.unit hx)) else 0) = 1

Next tactic:
have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
h1 : IsUnit.unit (_ : IsUnit 1) = 1
⊢ (if hx : IsUnit 1 then ↑(f (IsUnit.unit hx)) else 0) = 1

Next tactic:
simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    

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

Next tactic:
classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        by_cases hy : IsUnit y
        · simp only [hy, dif_pos]
          have hm : (IsUnit.mul_iff.mpr ⟨hx, hy⟩).unit = hx.unit * hy.unit := Units.eq_iff.mp rfl
          rw [hm, map_mul]
          norm_cast
        · simp only [hy, not_false_iff, dif_neg, mul_zero]
      · simp only [hx, IsUnit.mul_iff, false_and_iff, not_false_iff, dif_neg, zero_mul]
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      

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

Next tactic:
intro x y
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      

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

Next tactic:
by_cases hx : IsUnit x
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · 

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

Next tactic:
simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        

Proof state:
case pos
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
x y : R
hx : IsUnit x
⊢ (if h : IsUnit y then ↑(f (IsUnit.unit (_ : IsUnit (x * y)))) else 0) =
    ↑(f (IsUnit.unit (_ : IsUnit x))) * if hx : IsUnit y then ↑(f (IsUnit.unit hx)) else 0

Next tactic:
by_cases hy : IsUnit y
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        by_cases hy : IsUnit y
        · 

Proof state:
case pos
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
x y : R
hx : IsUnit x
hy : IsUnit y
⊢ (if h : IsUnit y then ↑(f (IsUnit.unit (_ : IsUnit (x * y)))) else 0) =
    ↑(f (IsUnit.unit (_ : IsUnit x))) * if hx : IsUnit y then ↑(f (IsUnit.unit hx)) else 0

Next tactic:
simp only [hy, dif_pos]
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        by_cases hy : IsUnit y
        · simp only [hy, dif_pos]
          

Proof state:
case pos
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
x y : R
hx : IsUnit x
hy : IsUnit y
⊢ ↑(f (IsUnit.unit (_ : IsUnit (x * y)))) = ↑(f (IsUnit.unit (_ : IsUnit x))) * ↑(f (IsUnit.unit (_ : IsUnit y)))

Next tactic:
have hm : (IsUnit.mul_iff.mpr ⟨hx, hy⟩).unit = hx.unit * hy.unit := Units.eq_iff.mp rfl
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        by_cases hy : IsUnit y
        · simp only [hy, dif_pos]
          have hm : (IsUnit.mul_iff.mpr ⟨hx, hy⟩).unit = hx.unit * hy.unit := Units.eq_iff.mp rfl
          

Proof state:
case pos
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
x y : R
hx : IsUnit x
hy : IsUnit y
hm : IsUnit.unit (_ : IsUnit (x * y)) = IsUnit.unit hx * IsUnit.unit hy
⊢ ↑(f (IsUnit.unit (_ : IsUnit (x * y)))) = ↑(f (IsUnit.unit (_ : IsUnit x))) * ↑(f (IsUnit.unit (_ : IsUnit y)))

Next tactic:
rw [hm, map_mul]
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        by_cases hy : IsUnit y
        · simp only [hy, dif_pos]
          have hm : (IsUnit.mul_iff.mpr ⟨hx, hy⟩).unit = hx.unit * hy.unit := Units.eq_iff.mp rfl
          rw [hm, map_mul]
          

Proof state:
case pos
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
x y : R
hx : IsUnit x
hy : IsUnit y
hm : IsUnit.unit (_ : IsUnit (x * y)) = IsUnit.unit hx * IsUnit.unit hy
⊢ ↑(f (IsUnit.unit hx) * f (IsUnit.unit hy)) = ↑(f (IsUnit.unit (_ : IsUnit x))) * ↑(f (IsUnit.unit (_ : IsUnit y)))

Next tactic:
norm_cast
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        by_cases hy : IsUnit y
        · simp only [hy, dif_pos]
          have hm : (IsUnit.mul_iff.mpr ⟨hx, hy⟩).unit = hx.unit * hy.unit := Units.eq_iff.mp rfl
          rw [hm, map_mul]
          norm_cast
        · 

Proof state:
case neg
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
x y : R
hx : IsUnit x
hy : ¬IsUnit y
⊢ (if h : IsUnit y then ↑(f (IsUnit.unit (_ : IsUnit (x * y)))) else 0) =
    ↑(f (IsUnit.unit (_ : IsUnit x))) * if hx : IsUnit y then ↑(f (IsUnit.unit hx)) else 0

Next tactic:
simp only [hy, not_false_iff, dif_neg, mul_zero]
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        by_cases hy : IsUnit y
        · simp only [hy, dif_pos]
          have hm : (IsUnit.mul_iff.mpr ⟨hx, hy⟩).unit = hx.unit * hy.unit := Units.eq_iff.mp rfl
          rw [hm, map_mul]
          norm_cast
        · simp only [hy, not_false_iff, dif_neg, mul_zero]
      · 

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

Next tactic:
simp only [hx, IsUnit.mul_iff, false_and_iff, not_false_iff, dif_neg, zero_mul]
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        by_cases hy : IsUnit y
        · simp only [hy, dif_pos]
          have hm : (IsUnit.mul_iff.mpr ⟨hx, hy⟩).unit = hx.unit * hy.unit := Units.eq_iff.mp rfl
          rw [hm, map_mul]
          norm_cast
        · simp only [hy, not_false_iff, dif_neg, mul_zero]
      · simp only [hx, IsUnit.mul_iff, false_and_iff, not_false_iff, dif_neg, zero_mul]
  map_nonunit' := by
    

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

Next tactic:
intro a ha
/-- Turn a homomorphism between unit groups into a `MulChar`. -/
noncomputable def ofUnitHom (f : Rˣ →* R'ˣ) : MulChar R R' where
  toFun := by classical exact fun x => if hx : IsUnit x then f hx.unit else 0
  map_one' := by
    have h1 : (isUnit_one.unit : Rˣ) = 1 := Units.eq_iff.mp rfl
    simp only [h1, dif_pos, Units.val_eq_one, map_one, isUnit_one]
  map_mul' := by
    classical
      intro x y
      by_cases hx : IsUnit x
      · simp only [hx, IsUnit.mul_iff, true_and_iff, dif_pos]
        by_cases hy : IsUnit y
        · simp only [hy, dif_pos]
          have hm : (IsUnit.mul_iff.mpr ⟨hx, hy⟩).unit = hx.unit * hy.unit := Units.eq_iff.mp rfl
          rw [hm, map_mul]
          norm_cast
        · simp only [hy, not_false_iff, dif_neg, mul_zero]
      · simp only [hx, IsUnit.mul_iff, false_and_iff, not_false_iff, dif_neg, zero_mul]
  map_nonunit' := by
    intro a ha
    

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

Next tactic:
simp only [ha, not_false_iff, dif_neg]
theorem ofUnitHom_coe (f : Rˣ →* R'ˣ) (a : Rˣ) : ofUnitHom f ↑a = f a := by 

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
a : Rˣ
⊢ (ofUnitHom f) ↑a = ↑(f a)

Next tactic:
simp [ofUnitHom]
/-- The equivalence between multiplicative characters and homomorphisms of unit groups. -/
noncomputable def equivToUnitHom : MulChar R R' ≃ (Rˣ →* R'ˣ) where
  toFun := toUnitHom
  invFun := ofUnitHom
  left_inv := by
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
⊢ Function.LeftInverse ofUnitHom toUnitHom

Next tactic:
intro χ
/-- The equivalence between multiplicative characters and homomorphisms of unit groups. -/
noncomputable def equivToUnitHom : MulChar R R' ≃ (Rˣ →* R'ˣ) where
  toFun := toUnitHom
  invFun := ofUnitHom
  left_inv := by
    intro χ
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
⊢ ofUnitHom (toUnitHom χ) = χ

Next tactic:
ext x
/-- The equivalence between multiplicative characters and homomorphisms of unit groups. -/
noncomputable def equivToUnitHom : MulChar R R' ≃ (Rˣ →* R'ˣ) where
  toFun := toUnitHom
  invFun := ofUnitHom
  left_inv := by
    intro χ
    ext x
    

Proof state:
case h
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
x : Rˣ
⊢ (ofUnitHom (toUnitHom χ)) ↑x = χ ↑x

Next tactic:
rw [ofUnitHom_coe, coe_toUnitHom]