-- Mathlib/Algebra/Group/Ext.lean
theorem DivInvMonoid.ext {M : Type*} ⦃m₁ m₂ : DivInvMonoid M⦄
    (h_mul : (letI := m₁; HMul.hMul : M → M → M) = (letI := m₂; HMul.hMul : M → M → M))
    (h_inv : (letI := m₁; Inv.inv : M → M) = (letI := m₂; Inv.inv : M → M)) : m₁ = m₂

Proof state:
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this : Monoid.npow = Monoid.npow
⊢ DivInvMonoid.zpow = DivInvMonoid.zpow

Tactic:
ext m x

Result:
case h.h
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this : Monoid.npow = Monoid.npow
m : ℤ
x : M
⊢ DivInvMonoid.zpow m x = DivInvMonoid.zpow m x

Proof state:
case h.h
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this : Monoid.npow = Monoid.npow
m : ℤ
x : M
⊢ DivInvMonoid.zpow m x = DivInvMonoid.zpow m x

Tactic:
exact @MonoidHom.map_zpow' M M m₁ m₂ f (congr_fun h_inv) x m

Result:
no goals

Proof state:
case mk.mk.mk
M : Type u_1
m₂ : DivInvMonoid M
toMonoid✝ : Monoid M
zpow✝ : ℤ → M → M
zpow_zero'✝ : ∀ (a : M), zpow✝ 0 a = 1
zpow_succ'✝ : ∀ (n : ℕ) (a : M), zpow✝ (↑n.succ) a = zpow✝ (↑n) a * a
inv✝ : M → M
zpow_neg'✝ : ∀ (n : ℕ) (a : M), zpow✝ (Int.negSucc n) a = (zpow✝ (↑n.succ) a)⁻¹
div✝ : M → M → M
div_eq_mul_inv✝ : ∀ (a b : M), a / b = a * b⁻¹
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝¹ : Monoid.npow = Monoid.npow
this✝ : DivInvMonoid.zpow = DivInvMonoid.zpow
this : Div.div = Div.div
⊢ mk div_eq_mul_inv✝ zpow✝ zpow_zero'✝ zpow_succ'✝ zpow_neg'✝ = m₂

Tactic:
rcases m₂ with @⟨_, ⟨_⟩, ⟨_⟩⟩

Result:
case mk.mk.mk.mk.mk.mk
M : Type u_1
toMonoid✝¹ : Monoid M
zpow✝¹ : ℤ → M → M
zpow_zero'✝¹ : ∀ (a : M), zpow✝¹ 0 a = 1
zpow_succ'✝¹ : ∀ (n : ℕ) (a : M), zpow✝¹ (↑n.succ) a = zpow✝¹ (↑n) a * a
inv✝¹ : M → M
zpow_neg'✝¹ : ∀ (n : ℕ) (a : M), zpow✝¹ (Int.negSucc n) a = (zpow✝¹ (↑n.succ) a)⁻¹
div✝¹ : M → M → M
div_eq_mul_inv✝¹ : ∀ (a b : M), a / b = a * b⁻¹
toMonoid✝ : Monoid M
zpow✝ : ℤ → M → M
zpow_zero'✝ : ∀ (a : M), zpow✝ 0 a = 1
zpow_succ'✝ : ∀ (n : ℕ) (a : M), zpow✝ (↑n.succ) a = zpow✝ (↑n) a * a
inv✝ : M → M
zpow_neg'✝ : ∀ (n : ℕ) (a : M), zpow✝ (Int.negSucc n) a = (zpow✝ (↑n.succ) a)⁻¹
div✝ : M → M → M
div_eq_mul_inv✝ : ∀ (a b : M), a / b = a * b⁻¹
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝¹ : Monoid.npow = Monoid.npow
this✝ : DivInvMonoid.zpow = DivInvMonoid.zpow
this : Div.div = Div.div
⊢ mk div_eq_mul_inv✝¹ zpow✝¹ zpow_zero'✝¹ zpow_succ'✝¹ zpow_neg'✝¹ =
    mk div_eq_mul_inv✝ zpow✝ zpow_zero'✝ zpow_succ'✝ zpow_neg'✝

Proof state:
case h.h
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝ : Monoid.npow = Monoid.npow
this : DivInvMonoid.zpow = DivInvMonoid.zpow
a b : M
⊢ Div.div a b = Div.div a b

Tactic:
exact @map_div' _ _
  (F := @MonoidHom _ _ (_) _) _ (id _) _
  (@MonoidHom.instMonoidHomClass _ _ (_) _) f (congr_fun h_inv) a b

Result:
no goals

Proof state:
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
⊢ m₁ = m₂

Tactic:
have h_mon := Monoid.ext h_mul

Result:
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
⊢ m₁ = m₂

Proof state:
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝ : Monoid.npow = Monoid.npow
this : DivInvMonoid.zpow = DivInvMonoid.zpow
⊢ Div.div = Div.div

Tactic:
ext a b

Result:
case h.h
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝ : Monoid.npow = Monoid.npow
this : DivInvMonoid.zpow = DivInvMonoid.zpow
a b : M
⊢ Div.div a b = Div.div a b

Proof state:
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝¹ : Monoid.npow = Monoid.npow
this✝ : DivInvMonoid.zpow = DivInvMonoid.zpow
this : Div.div = Div.div
⊢ m₁ = m₂

Tactic:
rcases m₁ with @⟨_, ⟨_⟩, ⟨_⟩⟩

Result:
case mk.mk.mk
M : Type u_1
m₂ : DivInvMonoid M
toMonoid✝ : Monoid M
zpow✝ : ℤ → M → M
zpow_zero'✝ : ∀ (a : M), zpow✝ 0 a = 1
zpow_succ'✝ : ∀ (n : ℕ) (a : M), zpow✝ (↑n.succ) a = zpow✝ (↑n) a * a
inv✝ : M → M
zpow_neg'✝ : ∀ (n : ℕ) (a : M), zpow✝ (Int.negSucc n) a = (zpow✝ (↑n.succ) a)⁻¹
div✝ : M → M → M
div_eq_mul_inv✝ : ∀ (a b : M), a / b = a * b⁻¹
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝¹ : Monoid.npow = Monoid.npow
this✝ : DivInvMonoid.zpow = DivInvMonoid.zpow
this : Div.div = Div.div
⊢ mk div_eq_mul_inv✝ zpow✝ zpow_zero'✝ zpow_succ'✝ zpow_neg'✝ = m₂

Proof state:
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this : Monoid.npow = Monoid.npow
⊢ m₁ = m₂

Tactic:
have : m₁.zpow = m₂.zpow := by
  ext m x
  exact @MonoidHom.map_zpow' M M m₁ m₂ f (congr_fun h_inv) x m

Result:
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝ : Monoid.npow = Monoid.npow
this : DivInvMonoid.zpow = DivInvMonoid.zpow
⊢ m₁ = m₂

Proof state:
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝ : Monoid.npow = Monoid.npow
this : DivInvMonoid.zpow = DivInvMonoid.zpow
⊢ m₁ = m₂

Tactic:
have : m₁.div = m₂.div := by
  ext a b
  exact @map_div' _ _
    (F := @MonoidHom _ _ (_) _) _ (id _) _
    (@MonoidHom.instMonoidHomClass _ _ (_) _) f (congr_fun h_inv) a b

Result:
M : Type u_1
m₁ m₂ : DivInvMonoid M
h_mul : HMul.hMul = HMul.hMul
h_inv : Inv.inv = Inv.inv
h_mon : toMonoid = toMonoid
h₁ : One.one = One.one
f : M →* M := { toFun := id, map_one' := h₁, map_mul' := ⋯ }
this✝¹ : Monoid.npow = Monoid.npow
this✝ : DivInvMonoid.zpow = DivInvMonoid.zpow
this : Div.div = Div.div
⊢ m₁ = m₂