l3lab/ntp-mathlib huggingface dataset:
theorem natDegree_multiset_prod (h : (0 : R[X]) ∉ t) :
    natDegree t.prod = (t.map natDegree).sum := by
  nontriviality R
  rw [natDegree_multiset_prod']
  simp_rw [Ne.def, Multiset.prod_eq_zero_iff, Multiset.mem_map, leadingCoeff_eq_zero]
  rintro ⟨_, h, rfl⟩
  

Proof state:
case h.intro.intro
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h✝ : 0 ∉ t
✝ : Nontrivial R
h : 0 ∈ t
⊢ False

Next tactic:
contradiction
/-- The leading coefficient of a product of polynomials is equal to
the product of the leading coefficients.

See `Polynomial.leadingCoeff_multiset_prod'` (with a `'`) for a version for commutative semirings,
where additionally, the product of the leading coefficients must be nonzero.
-/
theorem leadingCoeff_multiset_prod :
    t.prod.leadingCoeff = (t.map fun f => leadingCoeff f).prod := by
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
⊢ leadingCoeff (prod t) = prod (Multiset.map (fun f => leadingCoeff f) t)

Next tactic:
rw [← leadingCoeffHom_apply, MonoidHom.map_multiset_prod]
/-- The leading coefficient of a product of polynomials is equal to
the product of the leading coefficients.

See `Polynomial.leadingCoeff_multiset_prod'` (with a `'`) for a version for commutative semirings,
where additionally, the product of the leading coefficients must be nonzero.
-/
theorem leadingCoeff_multiset_prod :
    t.prod.leadingCoeff = (t.map fun f => leadingCoeff f).prod := by
  rw [← leadingCoeffHom_apply, MonoidHom.map_multiset_prod]
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
⊢ prod (Multiset.map (⇑leadingCoeffHom) t) = prod (Multiset.map (fun f => leadingCoeff f) t)

Next tactic:
rfl
/-- The leading coefficient of a product of polynomials is equal to
the product of the leading coefficients.

See `Polynomial.leadingCoeff_prod'` (with a `'`) for a version for commutative semirings,
where additionally, the product of the leading coefficients must be nonzero.
-/
theorem leadingCoeff_prod : (∏ i in s, f i).leadingCoeff = ∏ i in s, (f i).leadingCoeff := by
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
⊢ leadingCoeff (∏ i in s, f i) = ∏ i in s, leadingCoeff (f i)

Next tactic:
simpa using leadingCoeff_multiset_prod (s.1.map f)
@[to_additive]
instance OneHom.oneHomClass : OneHomClass (OneHom M N) M N where
  coe := OneHom.toFun
  coe_injective' f g h := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : One M
inst✝ : One N
f g : OneHom M N
h : f.toFun = g.toFun
⊢ f = g

Next tactic:
cases f
@[to_additive]
instance OneHom.oneHomClass : OneHomClass (OneHom M N) M N where
  coe := OneHom.toFun
  coe_injective' f g h := by cases f; 

Proof state:
case mk
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : One M
inst✝ : One N
g : OneHom M N
toFun✝ : M → N
map_one'✝ : toFun✝ 1 = 1
h : { toFun := toFun✝, map_one' := map_one'✝ }.toFun = g.toFun
⊢ { toFun := toFun✝, map_one' := map_one'✝ } = g

Next tactic:
cases g
@[to_additive]
instance OneHom.oneHomClass : OneHomClass (OneHom M N) M N where
  coe := OneHom.toFun
  coe_injective' f g h := by cases f; cases g; 

Proof state:
case mk.mk
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : One M
inst✝ : One N
toFun✝¹ : M → N
map_one'✝¹ : toFun✝¹ 1 = 1
toFun✝ : M → N
map_one'✝ : toFun✝ 1 = 1
h : { toFun := toFun✝¹, map_one' := map_one'✝¹ }.toFun = { toFun := toFun✝, map_one' := map_one'✝ }.toFun
⊢ { toFun := toFun✝¹, map_one' := map_one'✝¹ } = { toFun := toFun✝, map_one' := map_one'✝ }

Next tactic:
congr
/-- In principle this could be an instance, but in practice it causes performance issues. -/
@[to_additive]
theorem Subsingleton.of_oneHomClass [Subsingleton M] [OneHomClass F M N] :
    Subsingleton F where
  allEq f g := FunLike.ext _ _ fun x ↦ by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝³ : One M
inst✝² : One N
inst✝¹ : Subsingleton M
inst✝ : OneHomClass F M N
f g : F
x : M
⊢ f x = g x

Next tactic:
simp [Subsingleton.elim x 1]
@[to_additive]
theorem ne_one_of_map {R S F : Type*} [One R] [One S] [OneHomClass F R S] {f : F} {x : R}
    (hx : f x ≠ 1) : x ≠ 1 := ne_of_apply_ne f <| (by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F✝ : Type u_8
inst✝⁴ : One M
inst✝³ : One N
R : Type u_9
S : Type u_10
F : Type u_11
inst✝² : One R
inst✝¹ : One S
inst✝ : OneHomClass F R S
f : F
x : R
hx : f x ≠ 1
⊢ f x ≠ f 1

Next tactic:
rwa [(map_one f)]
/-- `MulHom` is a type of multiplication-preserving homomorphisms -/
@[to_additive "`AddHom` is a type of addition-preserving homomorphisms"]
instance MulHom.mulHomClass : MulHomClass (M →ₙ* N) M N where
  coe := MulHom.toFun
  coe_injective' f g h := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : Mul M
inst✝ : Mul N
f g : M →ₙ* N
h : f.toFun = g.toFun
⊢ f = g

Next tactic:
cases f
/-- `MulHom` is a type of multiplication-preserving homomorphisms -/
@[to_additive "`AddHom` is a type of addition-preserving homomorphisms"]
instance MulHom.mulHomClass : MulHomClass (M →ₙ* N) M N where
  coe := MulHom.toFun
  coe_injective' f g h := by cases f; 

Proof state:
case mk
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : Mul M
inst✝ : Mul N
g : M →ₙ* N
toFun✝ : M → N
map_mul'✝ : ∀ (x y : M), toFun✝ (x * y) = toFun✝ x * toFun✝ y
h : { toFun := toFun✝, map_mul' := map_mul'✝ }.toFun = g.toFun
⊢ { toFun := toFun✝, map_mul' := map_mul'✝ } = g

Next tactic:
cases g
/-- `MulHom` is a type of multiplication-preserving homomorphisms -/
@[to_additive "`AddHom` is a type of addition-preserving homomorphisms"]
instance MulHom.mulHomClass : MulHomClass (M →ₙ* N) M N where
  coe := MulHom.toFun
  coe_injective' f g h := by cases f; cases g; 

Proof state:
case mk.mk
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : Mul M
inst✝ : Mul N
toFun✝¹ : M → N
map_mul'✝¹ : ∀ (x y : M), toFun✝¹ (x * y) = toFun✝¹ x * toFun✝¹ y
toFun✝ : M → N
map_mul'✝ : ∀ (x y : M), toFun✝ (x * y) = toFun✝ x * toFun✝ y
h : { toFun := toFun✝¹, map_mul' := map_mul'✝¹ }.toFun = { toFun := toFun✝, map_mul' := map_mul'✝ }.toFun
⊢ { toFun := toFun✝¹, map_mul' := map_mul'✝¹ } = { toFun := toFun✝, map_mul' := map_mul'✝ }

Next tactic:
congr
@[to_additive]
instance MonoidHom.monoidHomClass : MonoidHomClass (M →* N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulOneClass M
inst✝ : MulOneClass N
f g : M →* N
h : (fun f => f.toFun) f = (fun f => f.toFun) g
⊢ f = g

Next tactic:
cases f
@[to_additive]
instance MonoidHom.monoidHomClass : MonoidHomClass (M →* N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    cases f
    

Proof state:
case mk
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulOneClass M
inst✝ : MulOneClass N
g : M →* N
toOneHom✝ : OneHom M N
map_mul'✝ : ∀ (x y : M), OneHom.toFun toOneHom✝ (x * y) = OneHom.toFun toOneHom✝ x * OneHom.toFun toOneHom✝ y
h : (fun f => f.toFun) { toOneHom := toOneHom✝, map_mul' := map_mul'✝ } = (fun f => f.toFun) g
⊢ { toOneHom := toOneHom✝, map_mul' := map_mul'✝ } = g

Next tactic:
cases g
@[to_additive]
instance MonoidHom.monoidHomClass : MonoidHomClass (M →* N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    cases f
    cases g
    

Proof state:
case mk.mk
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulOneClass M
inst✝ : MulOneClass N
toOneHom✝¹ : OneHom M N
map_mul'✝¹ : ∀ (x y : M), OneHom.toFun toOneHom✝¹ (x * y) = OneHom.toFun toOneHom✝¹ x * OneHom.toFun toOneHom✝¹ y
toOneHom✝ : OneHom M N
map_mul'✝ : ∀ (x y : M), OneHom.toFun toOneHom✝ (x * y) = OneHom.toFun toOneHom✝ x * OneHom.toFun toOneHom✝ y
h :
  (fun f => f.toFun) { toOneHom := toOneHom✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.toFun) { toOneHom := toOneHom✝, map_mul' := map_mul'✝ }
⊢ { toOneHom := toOneHom✝¹, map_mul' := map_mul'✝¹ } = { toOneHom := toOneHom✝, map_mul' := map_mul'✝ }

Next tactic:
congr
@[to_additive]
instance MonoidHom.monoidHomClass : MonoidHomClass (M →* N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    cases f
    cases g
    congr
    

Proof state:
case mk.mk.e_toOneHom
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulOneClass M
inst✝ : MulOneClass N
toOneHom✝¹ : OneHom M N
map_mul'✝¹ : ∀ (x y : M), OneHom.toFun toOneHom✝¹ (x * y) = OneHom.toFun toOneHom✝¹ x * OneHom.toFun toOneHom✝¹ y
toOneHom✝ : OneHom M N
map_mul'✝ : ∀ (x y : M), OneHom.toFun toOneHom✝ (x * y) = OneHom.toFun toOneHom✝ x * OneHom.toFun toOneHom✝ y
h :
  (fun f => f.toFun) { toOneHom := toOneHom✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.toFun) { toOneHom := toOneHom✝, map_mul' := map_mul'✝ }
⊢ toOneHom✝¹ = toOneHom✝

Next tactic:
apply FunLike.coe_injective'
@[to_additive]
instance MonoidHom.monoidHomClass : MonoidHomClass (M →* N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    cases f
    cases g
    congr
    apply FunLike.coe_injective'
    

Proof state:
case mk.mk.e_toOneHom.a
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulOneClass M
inst✝ : MulOneClass N
toOneHom✝¹ : OneHom M N
map_mul'✝¹ : ∀ (x y : M), OneHom.toFun toOneHom✝¹ (x * y) = OneHom.toFun toOneHom✝¹ x * OneHom.toFun toOneHom✝¹ y
toOneHom✝ : OneHom M N
map_mul'✝ : ∀ (x y : M), OneHom.toFun toOneHom✝ (x * y) = OneHom.toFun toOneHom✝ x * OneHom.toFun toOneHom✝ y
h :
  (fun f => f.toFun) { toOneHom := toOneHom✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.toFun) { toOneHom := toOneHom✝, map_mul' := map_mul'✝ }
⊢ ⇑toOneHom✝¹ = ⇑toOneHom✝

Next tactic:
exact h
@[to_additive]
theorem map_mul_eq_one [MonoidHomClass F M N] (f : F) {a b : M} (h : a * b = 1) : f a * f b = 1 :=
  by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝² : MulOneClass M
inst✝¹ : MulOneClass N
inst✝ : MonoidHomClass F M N
f : F
a b : M
h : a * b = 1
⊢ f a * f b = 1

Next tactic:
rw [← map_mul, h, map_one]
@[to_additive]
theorem map_div' [DivInvMonoid G] [DivInvMonoid H] [MonoidHomClass F G H]
    (f : F) (hf : ∀ a, f a⁻¹ = (f a)⁻¹) (a b : G) : f (a / b) = f a / f b := by
  

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : DivInvMonoid G
inst✝¹ : DivInvMonoid H
inst✝ : MonoidHomClass F G H
f : F
hf : ∀ (a : G), f a⁻¹ = (f a)⁻¹
a b : G
⊢ f (a / b) = f a / f b

Next tactic:
rw [div_eq_mul_inv, div_eq_mul_inv, map_mul, hf]
/-- Group homomorphisms preserve division. -/
@[to_additive "Additive group homomorphisms preserve subtraction."]
theorem map_mul_inv [Group G] [DivisionMonoid H] [MonoidHomClass F G H] (f : F) (a b : G) :
    f (a * b⁻¹) = f a * (f b)⁻¹ := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : Group G
inst✝¹ : DivisionMonoid H
inst✝ : MonoidHomClass F G H
f : F
a b : G
⊢ f (a * b⁻¹) = f a * (f b)⁻¹

Next tactic:
rw [map_mul, map_inv]
@[to_additive (attr := simp) (reorder := 8 9)]
theorem map_pow [Monoid G] [Monoid H] [MonoidHomClass F G H] (f : F) (a : G) :
    ∀ n : ℕ, f (a ^ n) = f a ^ n
  | 0 => by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : Monoid G
inst✝¹ : Monoid H
inst✝ : MonoidHomClass F G H
f : F
a : G
⊢ f (a ^ 0) = f a ^ 0

Next tactic:
rw [pow_zero, pow_zero, map_one]
@[to_additive (attr := simp) (reorder := 8 9)]
theorem map_pow [Monoid G] [Monoid H] [MonoidHomClass F G H] (f : F) (a : G) :
    ∀ n : ℕ, f (a ^ n) = f a ^ n
  | 0 => by rw [pow_zero, pow_zero, map_one]
  | n + 1 => by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : Monoid G
inst✝¹ : Monoid H
inst✝ : MonoidHomClass F G H
f : F
a : G
n : ℕ
⊢ f (a ^ (n + 1)) = f a ^ (n + 1)

Next tactic:
rw [pow_succ, pow_succ, map_mul, map_pow f a n]
@[to_additive]
theorem map_zpow' [DivInvMonoid G] [DivInvMonoid H] [MonoidHomClass F G H]
    (f : F) (hf : ∀ x : G, f x⁻¹ = (f x)⁻¹) (a : G) : ∀ n : ℤ, f (a ^ n) = f a ^ n
  | (n : ℕ) => by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : DivInvMonoid G
inst✝¹ : DivInvMonoid H
inst✝ : MonoidHomClass F G H
f : F
hf : ∀ (x : G), f x⁻¹ = (f x)⁻¹
a : G
n : ℕ
⊢ f (a ^ ↑n) = f a ^ ↑n

Next tactic:
rw [zpow_ofNat, map_pow, zpow_ofNat]
@[to_additive]
theorem map_zpow' [DivInvMonoid G] [DivInvMonoid H] [MonoidHomClass F G H]
    (f : F) (hf : ∀ x : G, f x⁻¹ = (f x)⁻¹) (a : G) : ∀ n : ℤ, f (a ^ n) = f a ^ n
  | (n : ℕ) => by rw [zpow_ofNat, map_pow, zpow_ofNat]
  | Int.negSucc n => by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : DivInvMonoid G
inst✝¹ : DivInvMonoid H
inst✝ : MonoidHomClass F G H
f : F
hf : ∀ (x : G), f x⁻¹ = (f x)⁻¹
a : G
n : ℕ
⊢ f (a ^ Int.negSucc n) = f a ^ Int.negSucc n

Next tactic:
rw [zpow_negSucc, hf, map_pow, ← zpow_negSucc]
instance MonoidWithZeroHom.monoidWithZeroHomClass : MonoidWithZeroHomClass (M →*₀ N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulZeroOneClass M
inst✝ : MulZeroOneClass N
f g : M →*₀ N
h : (fun f => f.toFun) f = (fun f => f.toFun) g
⊢ f = g

Next tactic:
cases f
instance MonoidWithZeroHom.monoidWithZeroHomClass : MonoidWithZeroHomClass (M →*₀ N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    cases f
    

Proof state:
case mk
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulZeroOneClass M
inst✝ : MulZeroOneClass N
g : M →*₀ N
toZeroHom✝ : ZeroHom M N
map_one'✝ : ZeroHom.toFun toZeroHom✝ 1 = 1
map_mul'✝ : ∀ (x y : M), ZeroHom.toFun toZeroHom✝ (x * y) = ZeroHom.toFun toZeroHom✝ x * ZeroHom.toFun toZeroHom✝ y
h : (fun f => f.toFun) { toZeroHom := toZeroHom✝, map_one' := map_one'✝, map_mul' := map_mul'✝ } = (fun f => f.toFun) g
⊢ { toZeroHom := toZeroHom✝, map_one' := map_one'✝, map_mul' := map_mul'✝ } = g

Next tactic:
cases g
instance MonoidWithZeroHom.monoidWithZeroHomClass : MonoidWithZeroHomClass (M →*₀ N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    cases f
    cases g
    

Proof state:
case mk.mk
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulZeroOneClass M
inst✝ : MulZeroOneClass N
toZeroHom✝¹ : ZeroHom M N
map_one'✝¹ : ZeroHom.toFun toZeroHom✝¹ 1 = 1
map_mul'✝¹ : ∀ (x y : M), ZeroHom.toFun toZeroHom✝¹ (x * y) = ZeroHom.toFun toZeroHom✝¹ x * ZeroHom.toFun toZeroHom✝¹ y
toZeroHom✝ : ZeroHom M N
map_one'✝ : ZeroHom.toFun toZeroHom✝ 1 = 1
map_mul'✝ : ∀ (x y : M), ZeroHom.toFun toZeroHom✝ (x * y) = ZeroHom.toFun toZeroHom✝ x * ZeroHom.toFun toZeroHom✝ y
h :
  (fun f => f.toFun) { toZeroHom := toZeroHom✝¹, map_one' := map_one'✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.toFun) { toZeroHom := toZeroHom✝, map_one' := map_one'✝, map_mul' := map_mul'✝ }
⊢ { toZeroHom := toZeroHom✝¹, map_one' := map_one'✝¹, map_mul' := map_mul'✝¹ } =
    { toZeroHom := toZeroHom✝, map_one' := map_one'✝, map_mul' := map_mul'✝ }

Next tactic:
congr
instance MonoidWithZeroHom.monoidWithZeroHomClass : MonoidWithZeroHomClass (M →*₀ N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    cases f
    cases g
    congr
    

Proof state:
case mk.mk.e_toZeroHom
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulZeroOneClass M
inst✝ : MulZeroOneClass N
toZeroHom✝¹ : ZeroHom M N
map_one'✝¹ : ZeroHom.toFun toZeroHom✝¹ 1 = 1
map_mul'✝¹ : ∀ (x y : M), ZeroHom.toFun toZeroHom✝¹ (x * y) = ZeroHom.toFun toZeroHom✝¹ x * ZeroHom.toFun toZeroHom✝¹ y
toZeroHom✝ : ZeroHom M N
map_one'✝ : ZeroHom.toFun toZeroHom✝ 1 = 1
map_mul'✝ : ∀ (x y : M), ZeroHom.toFun toZeroHom✝ (x * y) = ZeroHom.toFun toZeroHom✝ x * ZeroHom.toFun toZeroHom✝ y
h :
  (fun f => f.toFun) { toZeroHom := toZeroHom✝¹, map_one' := map_one'✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.toFun) { toZeroHom := toZeroHom✝, map_one' := map_one'✝, map_mul' := map_mul'✝ }
⊢ toZeroHom✝¹ = toZeroHom✝

Next tactic:
apply FunLike.coe_injective'
instance MonoidWithZeroHom.monoidWithZeroHomClass : MonoidWithZeroHomClass (M →*₀ N) M N where
  coe f := f.toFun
  coe_injective' f g h := by
    cases f
    cases g
    congr
    apply FunLike.coe_injective'
    

Proof state:
case mk.mk.e_toZeroHom.a
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : MulZeroOneClass M
inst✝ : MulZeroOneClass N
toZeroHom✝¹ : ZeroHom M N
map_one'✝¹ : ZeroHom.toFun toZeroHom✝¹ 1 = 1
map_mul'✝¹ : ∀ (x y : M), ZeroHom.toFun toZeroHom✝¹ (x * y) = ZeroHom.toFun toZeroHom✝¹ x * ZeroHom.toFun toZeroHom✝¹ y
toZeroHom✝ : ZeroHom M N
map_one'✝ : ZeroHom.toFun toZeroHom✝ 1 = 1
map_mul'✝ : ∀ (x y : M), ZeroHom.toFun toZeroHom✝ (x * y) = ZeroHom.toFun toZeroHom✝ x * ZeroHom.toFun toZeroHom✝ y
h :
  (fun f => f.toFun) { toZeroHom := toZeroHom✝¹, map_one' := map_one'✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.toFun) { toZeroHom := toZeroHom✝, map_one' := map_one'✝, map_mul' := map_mul'✝ }
⊢ ⇑toZeroHom✝¹ = ⇑toZeroHom✝

Next tactic:
exact h
/-- Makes a group homomorphism from a proof that the map preserves multiplication. -/
@[to_additive (attr := simps (config := .asFn))
  "Makes an additive group homomorphism from a proof that the map preserves addition."]
def mk' (f : M → G) (map_mul : ∀ a b : M, f (a * b) = f a * f b) : M →* G where
  toFun := f
  map_mul' := map_mul
  map_one' := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝¹ : Group G
inst✝ : MulOneClass M
f : M → G
map_mul : ∀ (a b : M), f (a * b) = f a * f b
⊢ f 1 = 1

Next tactic:
rw [← mul_right_cancel_iff, ← map_mul _ 1, one_mul, one_mul]
/-- Composition of `OneHom`s as a `OneHom`. -/
@[to_additive]
def OneHom.comp [One M] [One N] [One P] (hnp : OneHom N P) (hmn : OneHom M N) : OneHom M P where
  toFun := hnp ∘ hmn
  map_one' := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝² : One M
inst✝¹ : One N
inst✝ : One P
hnp : OneHom N P
hmn : OneHom M N
⊢ (⇑hnp ∘ ⇑hmn) 1 = 1

Next tactic:
simp
/-- Composition of `MulHom`s as a `MulHom`. -/
@[to_additive]
def MulHom.comp [Mul M] [Mul N] [Mul P] (hnp : N →ₙ* P) (hmn : M →ₙ* N) : M →ₙ* P where
  toFun := hnp ∘ hmn
  map_mul' x y := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝² : Mul M
inst✝¹ : Mul N
inst✝ : Mul P
hnp : N →ₙ* P
hmn : M →ₙ* N
x y : M
⊢ (⇑hnp ∘ ⇑hmn) (x * y) = (⇑hnp ∘ ⇑hmn) x * (⇑hnp ∘ ⇑hmn) y

Next tactic:
simp
/-- Composition of monoid morphisms as a monoid morphism. -/
@[to_additive]
def MonoidHom.comp [MulOneClass M] [MulOneClass N] [MulOneClass P] (hnp : N →* P) (hmn : M →* N) :
    M →* P where
  toFun := hnp ∘ hmn
  map_one' := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝² : MulOneClass M
inst✝¹ : MulOneClass N
inst✝ : MulOneClass P
hnp : N →* P
hmn : M →* N
⊢ (⇑hnp ∘ ⇑hmn) 1 = 1

Next tactic:
simp
/-- Composition of monoid morphisms as a monoid morphism. -/
@[to_additive]
def MonoidHom.comp [MulOneClass M] [MulOneClass N] [MulOneClass P] (hnp : N →* P) (hmn : M →* N) :
    M →* P where
  toFun := hnp ∘ hmn
  map_one' := by simp
  map_mul' := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝² : MulOneClass M
inst✝¹ : MulOneClass N
inst✝ : MulOneClass P
hnp : N →* P
hmn : M →* N
⊢ ∀ (x y : M),
    OneHom.toFun { toFun := ⇑hnp ∘ ⇑hmn, map_one' := (_ : hnp (hmn 1) = 1) } (x * y) =
      OneHom.toFun { toFun := ⇑hnp ∘ ⇑hmn, map_one' := (_ : hnp (hmn 1) = 1) } x *
        OneHom.toFun { toFun := ⇑hnp ∘ ⇑hmn, map_one' := (_ : hnp (hmn 1) = 1) } y

Next tactic:
simp
/-- Composition of `MonoidWithZeroHom`s as a `MonoidWithZeroHom`. -/
def MonoidWithZeroHom.comp [MulZeroOneClass M] [MulZeroOneClass N] [MulZeroOneClass P]
    (hnp : N →*₀ P) (hmn : M →*₀ N) : M →*₀ P where
  toFun := hnp ∘ hmn
  map_zero' := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝² : MulZeroOneClass M
inst✝¹ : MulZeroOneClass N
inst✝ : MulZeroOneClass P
hnp : N →*₀ P
hmn : M →*₀ N
⊢ (⇑hnp ∘ ⇑hmn) 0 = 0

Next tactic:
rw [Function.comp_apply, map_zero, map_zero]
/-- Composition of `MonoidWithZeroHom`s as a `MonoidWithZeroHom`. -/
def MonoidWithZeroHom.comp [MulZeroOneClass M] [MulZeroOneClass N] [MulZeroOneClass P]
    (hnp : N →*₀ P) (hmn : M →*₀ N) : M →*₀ P where
  toFun := hnp ∘ hmn
  map_zero' := by rw [Function.comp_apply, map_zero, map_zero]
  map_one' := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝² : MulZeroOneClass M
inst✝¹ : MulZeroOneClass N
inst✝ : MulZeroOneClass P
hnp : N →*₀ P
hmn : M →*₀ N
⊢ ZeroHom.toFun { toFun := ⇑hnp ∘ ⇑hmn, map_zero' := (_ : (⇑hnp ∘ ⇑hmn) 0 = 0) } 1 = 1

Next tactic:
simp
/-- Composition of `MonoidWithZeroHom`s as a `MonoidWithZeroHom`. -/
def MonoidWithZeroHom.comp [MulZeroOneClass M] [MulZeroOneClass N] [MulZeroOneClass P]
    (hnp : N →*₀ P) (hmn : M →*₀ N) : M →*₀ P where
  toFun := hnp ∘ hmn
  map_zero' := by rw [Function.comp_apply, map_zero, map_zero]
  map_one' := by simp
  map_mul' := by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝² : MulZeroOneClass M
inst✝¹ : MulZeroOneClass N
inst✝ : MulZeroOneClass P
hnp : N →*₀ P
hmn : M →*₀ N
⊢ ∀ (x y : M),
    ZeroHom.toFun { toFun := ⇑hnp ∘ ⇑hmn, map_zero' := (_ : (⇑hnp ∘ ⇑hmn) 0 = 0) } (x * y) =
      ZeroHom.toFun { toFun := ⇑hnp ∘ ⇑hmn, map_zero' := (_ : (⇑hnp ∘ ⇑hmn) 0 = 0) } x *
        ZeroHom.toFun { toFun := ⇑hnp ∘ ⇑hmn, map_zero' := (_ : (⇑hnp ∘ ⇑hmn) 0 = 0) } y

Next tactic:
simp
@[to_additive]
theorem OneHom.cancel_left [One M] [One N] [One P] {g : OneHom N P} {f₁ f₂ : OneHom M N}
    (hg : Function.Injective g) : g.comp f₁ = g.comp f₂ ↔ f₁ = f₂ :=
  ⟨fun h => OneHom.ext fun x => hg <| by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
G : Type u_6
H : Type u_7
F : Type u_8
inst✝² : One M
inst✝¹ : One N
inst✝ : One P
g : OneHom N P
f₁ f₂ : OneHom M N
hg : Function.Injective ⇑g
h : comp g f₁ = comp g f₂
x : M
⊢ g (f₁ x) = g (f₂ x)

Next tactic:
rw [← OneHom.comp_apply, h, OneHom.comp_apply]