File: Mathlib/Algebra/Group/Equiv/Basic.lean

full_name: ZeroHom.inverse_apply
code: /-- Makes a `OneHom` inverse from the bijective inverse of a `OneHom` -/
@[to_additive (attr := simps)
  "Make a `ZeroHom` inverse from the bijective inverse of a `ZeroHom`"]
def OneHom.inverse [One M] [One N]
    (f : OneHom M N) (g : N → M)
    (h₁ : Function.LeftInverse g f) :
  OneHom N M 
goal: ∀ (a : N), (f.inverse g h₁) a = g a

full_name: OneHom.inverse_apply
code: /-- Makes a `OneHom` inverse from the bijective inverse of a `OneHom` -/
@[to_additive (attr := simps)
  "Make a `ZeroHom` inverse from the bijective inverse of a `ZeroHom`"]
def OneHom.inverse [One M] [One N]
    (f : OneHom M N) (g : N → M)
    (h₁ : Function.LeftInverse g f) :
  OneHom N M 
goal: ∀ (a : N), (f.inverse g h₁) a = g a

full_name: OneHom.inverse
code: /-- Makes a `OneHom` inverse from the bijective inverse of a `OneHom` -/
@[to_additive (attr := simps)
  "Make a `ZeroHom` inverse from the bijective inverse of a `ZeroHom`"]
def OneHom.inverse [One M] [One N]
    (f : OneHom M N) (g : N → M)
    (h₁ : Function.LeftInverse g f) :
  OneHom N M 
goal: OneHom N M

full_name: ZeroHom.inverse
code: /-- Makes a `OneHom` inverse from the bijective inverse of a `OneHom` -/
@[to_additive (attr := simps)
  "Make a `ZeroHom` inverse from the bijective inverse of a `ZeroHom`"]
def OneHom.inverse [One M] [One N]
    (f : OneHom M N) (g : N → M)
    (h₁ : Function.LeftInverse g f) :
  OneHom N M 
goal: ZeroHom N M

full_name: MulHom.inverse
code: /-- Makes a multiplicative inverse from a bijection which preserves multiplication. -/
@[to_additive (attr := simps)
  "Makes an additive inverse from a bijection which preserves addition."]
def MulHom.inverse [Mul M] [Mul N] (f : M →ₙ* N) (g : N → M)
    (h₁ : Function.LeftInverse g f)
    (h₂ : Function.RightInverse g f) : N →ₙ* M 
goal: N →ₙ* M

full_name: MulHom.inverse_apply
code: /-- Makes a multiplicative inverse from a bijection which preserves multiplication. -/
@[to_additive (attr := simps)
  "Makes an additive inverse from a bijection which preserves addition."]
def MulHom.inverse [Mul M] [Mul N] (f : M →ₙ* N) (g : N → M)
    (h₁ : Function.LeftInverse g f)
    (h₂ : Function.RightInverse g f) : N →ₙ* M 
goal: ∀ (a : N), (f.inverse g h₁ h₂) a = g a

full_name: AddHom.inverse_apply
code: /-- Makes a multiplicative inverse from a bijection which preserves multiplication. -/
@[to_additive (attr := simps)
  "Makes an additive inverse from a bijection which preserves addition."]
def MulHom.inverse [Mul M] [Mul N] (f : M →ₙ* N) (g : N → M)
    (h₁ : Function.LeftInverse g f)
    (h₂ : Function.RightInverse g f) : N →ₙ* M 
goal: ∀ (a : N), (f.inverse g h₁ h₂) a = g a

full_name: AddHom.inverse
code: /-- Makes a multiplicative inverse from a bijection which preserves multiplication. -/
@[to_additive (attr := simps)
  "Makes an additive inverse from a bijection which preserves addition."]
def MulHom.inverse [Mul M] [Mul N] (f : M →ₙ* N) (g : N → M)
    (h₁ : Function.LeftInverse g f)
    (h₂ : Function.RightInverse g f) : N →ₙ* M 
goal: AddHom N M

full_name: AddMonoidHom.inverse_apply
code: /-- The inverse of a bijective `MonoidHom` is a `MonoidHom`. -/
@[to_additive (attr := simps)
  "The inverse of a bijective `AddMonoidHom` is an `AddMonoidHom`."]
def MonoidHom.inverse {A B : Type*} [Monoid A] [Monoid B] (f : A →* B) (g : B → A)
    (h₁ : Function.LeftInverse g f) (h₂ : Function.RightInverse g f) : B →* A 
goal: ∀ (a : B), (f.inverse g h₁ h₂) a = g a

full_name: AddMonoidHom.inverse
code: /-- The inverse of a bijective `MonoidHom` is a `MonoidHom`. -/
@[to_additive (attr := simps)
  "The inverse of a bijective `AddMonoidHom` is an `AddMonoidHom`."]
def MonoidHom.inverse {A B : Type*} [Monoid A] [Monoid B] (f : A →* B) (g : B → A)
    (h₁ : Function.LeftInverse g f) (h₂ : Function.RightInverse g f) : B →* A 
goal: B →+ A

full_name: MonoidHom.inverse_apply
code: /-- The inverse of a bijective `MonoidHom` is a `MonoidHom`. -/
@[to_additive (attr := simps)
  "The inverse of a bijective `AddMonoidHom` is an `AddMonoidHom`."]
def MonoidHom.inverse {A B : Type*} [Monoid A] [Monoid B] (f : A →* B) (g : B → A)
    (h₁ : Function.LeftInverse g f) (h₂ : Function.RightInverse g f) : B →* A 
goal: ∀ (a : B), (f.inverse g h₁ h₂) a = g a

full_name: MonoidHom.inverse
code: /-- The inverse of a bijective `MonoidHom` is a `MonoidHom`. -/
@[to_additive (attr := simps)
  "The inverse of a bijective `AddMonoidHom` is an `AddMonoidHom`."]
def MonoidHom.inverse {A B : Type*} [Monoid A] [Monoid B] (f : A →* B) (g : B → A)
    (h₁ : Function.LeftInverse g f) (h₂ : Function.RightInverse g f) : B →* A 
goal: B →* A

full_name: AddEquiv
code: /-- `AddEquiv α β` is the type of an equiv `α ≃ β` which preserves addition. -/
structure AddEquiv (A B : Type*) [Add A] [Add B] extends A ≃ B, AddHom A B
goal: Type (max u_12 u_13)

full_name: AddEquivClass
code: /-- `AddEquivClass F A B` states that `F` is a type of addition-preserving morphisms.
You should extend this class when you extend `AddEquiv`. -/
class AddEquivClass (F : Type*) (A B : outParam Type*) [Add A] [Add B] [EquivLike F A B] :
    Prop where
  /-- Preserves addition. -/
  map_add : ∀ (f : F) (a b), f (a + b) = f a + f b
goal: Prop

full_name: AddEquivClass.map_add
code: /-- `AddEquivClass F A B` states that `F` is a type of addition-preserving morphisms.
You should extend this class when you extend `AddEquiv`. -/
class AddEquivClass (F : Type*) (A B : outParam Type*) [Add A] [Add B] [EquivLike F A B] :
    Prop where
  /-- Preserves addition. -/
  map_add : ∀ (f : F) (a b), f (a + b) = f a + f b
goal: f (a + b) = f a + f b

full_name: MulEquiv
code: /-- `MulEquiv α β` is the type of an equiv `α ≃ β` which preserves multiplication. -/
@[to_additive]
structure MulEquiv (M N : Type*) [Mul M] [Mul N] extends M ≃ N, M →ₙ* N
goal: Type (max u_12 u_13)

full_name: MulEquivClass.map_mul
code: /-- `MulEquivClass F A B` states that `F` is a type of multiplication-preserving morphisms.
You should extend this class when you extend `MulEquiv`. -/
-- TODO: make this a synonym for MulHomClass?
@[to_additive]
class MulEquivClass (F : Type*) (A B : outParam Type*) [Mul A] [Mul B] [EquivLike F A B] :
    Prop where
  /-- Preserves multiplication. -/
  map_mul : ∀ (f : F) (a b), f (a * b) = f a * f b
goal: f (a * b) = f a * f b

full_name: MulEquivClass
code: /-- `MulEquivClass F A B` states that `F` is a type of multiplication-preserving morphisms.
You should extend this class when you extend `MulEquiv`. -/
-- TODO: make this a synonym for MulHomClass?
@[to_additive]
class MulEquivClass (F : Type*) (A B : outParam Type*) [Mul A] [Mul B] [EquivLike F A B] :
    Prop where
  /-- Preserves multiplication. -/
  map_mul : ∀ (f : F) (a b), f (a * b) = f a * f b
goal: Prop

full_name: _aux_Mathlib_Algebra_Group_Equiv_Basic___unexpand_MulEquiv_1
code: /-- Notation for a `MulEquiv`. -/
infixl:25 " ≃* " => MulEquiv
goal: Lean.PrettyPrinter.Unexpander

full_name: «_aux_Mathlib_Algebra_Group_Equiv_Basic___macroRules_term_≃*__1»
code: /-- Notation for a `MulEquiv`. -/
infixl:25 " ≃* " => MulEquiv
goal: Lean.Macro

full_name: «_aux_Mathlib_Algebra_Group_Equiv_Basic___macroRules_term_≃+__1»
code: /-- Notation for an `AddEquiv`. -/
infixl:25 " ≃+ " => AddEquiv
goal: Lean.Macro

full_name: _aux_Mathlib_Algebra_Group_Equiv_Basic___unexpand_AddEquiv_1
code: /-- Notation for an `AddEquiv`. -/
infixl:25 " ≃+ " => AddEquiv
goal: Lean.PrettyPrinter.Unexpander

full_name: MulEquivClass.instMulHomClass
code: @[to_additive]
instance (priority := 100) instMulHomClass (F : Type*)
    [Mul M] [Mul N] [EquivLike F M N] [h : MulEquivClass F M N] : MulHomClass F M N 
goal: MulHomClass F M N

full_name: AddEquivClass.instAddHomClass
code: @[to_additive]
instance (priority := 100) instMulHomClass (F : Type*)
    [Mul M] [Mul N] [EquivLike F M N] [h : MulEquivClass F M N] : MulHomClass F M N 
goal: AddHomClass F M N

full_name: MulEquivClass.instMonoidHomClass
code: @[to_additive]
instance (priority := 100) instMonoidHomClass
    [MulOneClass M] [MulOneClass N] [MulEquivClass F M N] :
    MonoidHomClass F M N 
goal: MonoidHomClass F M N

full_name: AddEquivClass.instAddMonoidHomClass
code: @[to_additive]
instance (priority := 100) instMonoidHomClass
    [MulOneClass M] [MulOneClass N] [MulEquivClass F M N] :
    MonoidHomClass F M N 
goal: AddMonoidHomClass F M N

full_name: MulEquivClass.map_eq_one_iff
code: @[to_additive (attr := simp)]
theorem map_eq_one_iff {M N} [MulOneClass M] [MulOneClass N] [EquivLike F M N] [MulEquivClass F M N]
    (h : F) {x : M} :
    h x = 1 ↔ x = 1 
goal: h x = 1 ↔ x = 1

full_name: AddEquivClass.map_eq_zero_iff
code: @[to_additive (attr := simp)]
theorem map_eq_one_iff {M N} [MulOneClass M] [MulOneClass N] [EquivLike F M N] [MulEquivClass F M N]
    (h : F) {x : M} :
    h x = 1 ↔ x = 1 
goal: h x = 0 ↔ x = 0

full_name: MulEquivClass.map_ne_one_iff
code: @[to_additive]
theorem map_ne_one_iff {M N} [MulOneClass M] [MulOneClass N] [EquivLike F M N] [MulEquivClass F M N]
    (h : F) {x : M} :
    h x ≠ 1 ↔ x ≠ 1 
goal: h x ≠ 1 ↔ x ≠ 1

full_name: AddEquivClass.map_ne_zero_iff
code: @[to_additive]
theorem map_ne_one_iff {M N} [MulOneClass M] [MulOneClass N] [EquivLike F M N] [MulEquivClass F M N]
    (h : F) {x : M} :
    h x ≠ 1 ↔ x ≠ 1 
goal: h x ≠ 0 ↔ x ≠ 0

full_name: AddEquivClass.toAddEquiv
code: /-- Turn an element of a type `F` satisfying `MulEquivClass F α β` into an actual
`MulEquiv`. This is declared as the default coercion from `F` to `α ≃* β`. -/
@[to_additive (attr := coe)
"Turn an element of a type `F` satisfying `AddEquivClass F α β` into an actual
`AddEquiv`. This is declared as the default coercion from `F` to `α ≃+ β`."]
def MulEquivClass.toMulEquiv [Mul α] [Mul β] [MulEquivClass F α β] (f : F) : α ≃* β 
goal: α ≃+ β

full_name: MulEquivClass.toMulEquiv
code: /-- Turn an element of a type `F` satisfying `MulEquivClass F α β` into an actual
`MulEquiv`. This is declared as the default coercion from `F` to `α ≃* β`. -/
@[to_additive (attr := coe)
"Turn an element of a type `F` satisfying `AddEquivClass F α β` into an actual
`AddEquiv`. This is declared as the default coercion from `F` to `α ≃+ β`."]
def MulEquivClass.toMulEquiv [Mul α] [Mul β] [MulEquivClass F α β] (f : F) : α ≃* β 
goal: α ≃* β

full_name: instCoeTCMulEquivOfMulEquivClass
code: /-- Any type satisfying `MulEquivClass` can be cast into `MulEquiv` via
`MulEquivClass.toMulEquiv`. -/
@[to_additive "Any type satisfying `AddEquivClass` can be cast into `AddEquiv` via
`AddEquivClass.toAddEquiv`. "]
instance [Mul α] [Mul β] [MulEquivClass F α β] : CoeTC F (α ≃* β) 
goal: CoeTC F (α ≃* β)

full_name: instCoeTCAddEquivOfAddEquivClass
code: /-- Any type satisfying `MulEquivClass` can be cast into `MulEquiv` via
`MulEquivClass.toMulEquiv`. -/
@[to_additive "Any type satisfying `AddEquivClass` can be cast into `AddEquiv` via
`AddEquivClass.toAddEquiv`. "]
instance [Mul α] [Mul β] [MulEquivClass F α β] : CoeTC F (α ≃* β) 
goal: CoeTC F (α ≃+ β)

full_name: MulEquivClass.toMulEquiv_injective
code: @[to_additive]
theorem MulEquivClass.toMulEquiv_injective [Mul α] [Mul β] [MulEquivClass F α β] :
    Function.Injective ((↑) : F → α ≃* β) 
goal: Function.Injective MulEquivClass.toMulEquiv

full_name: AddEquivClass.toAddEquiv_injective
code: @[to_additive]
theorem MulEquivClass.toMulEquiv_injective [Mul α] [Mul β] [MulEquivClass F α β] :
    Function.Injective ((↑) : F → α ≃* β) 
goal: Function.Injective AddEquivClass.toAddEquiv

full_name: AddEquiv.instEquivLike
code: @[to_additive]
instance : EquivLike (M ≃* N) M N 
goal: EquivLike (M ≃+ N) M N

full_name: MulEquiv.instEquivLike
code: @[to_additive]
instance : EquivLike (M ≃* N) M N 
goal: EquivLike (M ≃* N) M N

full_name: AddEquiv.instAddEquivClass
code: @[to_additive]
instance : MulEquivClass (M ≃* N) M N 
goal: AddEquivClass (M ≃+ N) M N

full_name: MulEquiv.instMulEquivClass
code: @[to_additive]
instance : MulEquivClass (M ≃* N) M N 
goal: MulEquivClass (M ≃* N) M N

full_name: AddEquiv.instCoeFunForall
code: @[to_additive] -- shortcut instance that doesn't generate any subgoals
instance : CoeFun (M ≃* N) fun _ ↦ M → N 
goal: CoeFun (M ≃+ N) fun x => M → N

full_name: MulEquiv.instCoeFunForall
code: @[to_additive] -- shortcut instance that doesn't generate any subgoals
instance : CoeFun (M ≃* N) fun _ ↦ M → N 
goal: CoeFun (M ≃* N) fun x => M → N

full_name: MulEquiv.toEquiv_eq_coe
code: @[to_additive (attr := simp)]
theorem toEquiv_eq_coe (f : M ≃* N) : f.toEquiv = f 
goal: f.toEquiv = ↑f

full_name: AddEquiv.toEquiv_eq_coe
code: @[to_additive (attr := simp)]
theorem toEquiv_eq_coe (f : M ≃* N) : f.toEquiv = f 
goal: f.toEquiv = ↑f

full_name: MulEquiv.toMulHom_eq_coe
code: @[to_additive (attr := simp)]
theorem toMulHom_eq_coe (f : M ≃* N) : f.toMulHom = ↑f 
goal: f.toMulHom = ↑f

full_name: AddEquiv.toAddHom_eq_coe
code: @[to_additive (attr := simp)]
theorem toMulHom_eq_coe (f : M ≃* N) : f.toMulHom = ↑f 
goal: f.toAddHom = ↑f

full_name: MulEquiv.coe_toEquiv
code: @[to_additive (attr := simp)]
theorem coe_toEquiv (f : M ≃* N) : ⇑(f : M ≃ N) = f 
goal: ⇑↑f = ⇑f

full_name: AddEquiv.coe_toEquiv
code: @[to_additive (attr := simp)]
theorem coe_toEquiv (f : M ≃* N) : ⇑(f : M ≃ N) = f 
goal: ⇑↑f = ⇑f

full_name: MulEquiv.coe_toMulHom
code: @[to_additive (attr := simp 1100)]
theorem coe_toMulHom {f : M ≃* N} : (f.toMulHom : M → N) = f 
goal: ⇑f.toMulHom = ⇑f

full_name: AddEquiv.coe_toAddHom
code: @[to_additive (attr := simp 1100)]
theorem coe_toMulHom {f : M ≃* N} : (f.toMulHom : M → N) = f 
goal: ⇑f.toAddHom = ⇑f

full_name: AddEquiv.map_add
code: /-- A multiplicative isomorphism preserves multiplication. -/
@[to_additive "An additive isomorphism preserves addition."]
protected theorem map_mul (f : M ≃* N) : ∀ x y, f (x * y) = f x * f y 
goal: f (x + y) = f x + f y

full_name: MulEquiv.map_mul
code: /-- A multiplicative isomorphism preserves multiplication. -/
@[to_additive "An additive isomorphism preserves addition."]
protected theorem map_mul (f : M ≃* N) : ∀ x y, f (x * y) = f x * f y 
goal: f (x * y) = f x * f y

full_name: AddEquiv.mk'
code: /-- Makes a multiplicative isomorphism from a bijection which preserves multiplication. -/
@[to_additive "Makes an additive isomorphism from a bijection which preserves addition."]
def mk' (f : M ≃ N) (h : ∀ x y, f (x * y) = f x * f y) : M ≃* N 
goal: M ≃+ N

full_name: MulEquiv.mk'
code: /-- Makes a multiplicative isomorphism from a bijection which preserves multiplication. -/
@[to_additive "Makes an additive isomorphism from a bijection which preserves addition."]
def mk' (f : M ≃ N) (h : ∀ x y, f (x * y) = f x * f y) : M ≃* N 
goal: M ≃* N

full_name: MulEquiv.bijective
code: @[to_additive]
protected theorem bijective (e : M ≃* N) : Function.Bijective e 
goal: Function.Bijective ⇑e

full_name: AddEquiv.bijective
code: @[to_additive]
protected theorem bijective (e : M ≃* N) : Function.Bijective e 
goal: Function.Bijective ⇑e

full_name: AddEquiv.injective
code: @[to_additive]
protected theorem injective (e : M ≃* N) : Function.Injective e 
goal: Function.Injective ⇑e

full_name: MulEquiv.injective
code: @[to_additive]
protected theorem injective (e : M ≃* N) : Function.Injective e 
goal: Function.Injective ⇑e

full_name: AddEquiv.surjective
code: @[to_additive]
protected theorem surjective (e : M ≃* N) : Function.Surjective e 
goal: Function.Surjective ⇑e

full_name: MulEquiv.surjective
code: @[to_additive]
protected theorem surjective (e : M ≃* N) : Function.Surjective e 
goal: Function.Surjective ⇑e

full_name: AddEquiv.refl
code: /-- The identity map is a multiplicative isomorphism. -/
@[to_additive (attr := refl) "The identity map is an additive isomorphism."]
def refl (M : Type*) [Mul M] : M ≃* M 
goal: M ≃+ M

full_name: MulEquiv.refl
code: /-- The identity map is a multiplicative isomorphism. -/
@[to_additive (attr := refl) "The identity map is an additive isomorphism."]
def refl (M : Type*) [Mul M] : M ≃* M 
goal: M ≃* M

full_name: MulEquiv.instInhabited
code: @[to_additive]
instance : Inhabited (M ≃* M) 
goal: Inhabited (M ≃* M)

full_name: AddEquiv.instInhabited
code: @[to_additive]
instance : Inhabited (M ≃* M) 
goal: Inhabited (M ≃+ M)

full_name: MulEquiv.symm_map_mul
code: /-- An alias for `h.symm.map_mul`. Introduced to fix the issue in
https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/!4.234183.20.60simps.60.20maximum.20recursion.20depth
-/
@[to_additive]
lemma symm_map_mul {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) (x y : N) :
    h.symm (x * y) = h.symm x * h.symm y 
goal: h.symm (x * y) = h.symm x * h.symm y

full_name: AddEquiv.symm_map_add
code: /-- An alias for `h.symm.map_mul`. Introduced to fix the issue in
https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/!4.234183.20.60simps.60.20maximum.20recursion.20depth
-/
@[to_additive]
lemma symm_map_mul {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) (x y : N) :
    h.symm (x * y) = h.symm x * h.symm y 
goal: h.symm (x + y) = h.symm x + h.symm y

full_name: MulEquiv.symm
code: /-- The inverse of an isomorphism is an isomorphism. -/
@[to_additive (attr := symm) "The inverse of an isomorphism is an isomorphism."]
def symm {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) : N ≃* M 
goal: N ≃* M

full_name: AddEquiv.symm
code: /-- The inverse of an isomorphism is an isomorphism. -/
@[to_additive (attr := symm) "The inverse of an isomorphism is an isomorphism."]
def symm {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) : N ≃* M 
goal: N ≃+ M

full_name: MulEquiv.invFun_eq_symm
code: @[to_additive] -- Porting note: no longer a `simp`, see below
theorem invFun_eq_symm {f : M ≃* N} : f.invFun = f.symm 
goal: f.invFun = ⇑f.symm

full_name: AddEquiv.invFun_eq_symm
code: @[to_additive] -- Porting note: no longer a `simp`, see below
theorem invFun_eq_symm {f : M ≃* N} : f.invFun = f.symm 
goal: f.invFun = ⇑f.symm

full_name: AddEquiv.coe_toEquiv_symm
code: @[to_additive (attr := simp)]
theorem coe_toEquiv_symm (f : M ≃* N) : ((f : M ≃ N).symm : N → M) = f.symm 
goal: ⇑(↑f).symm = ⇑f.symm

full_name: MulEquiv.coe_toEquiv_symm
code: @[to_additive (attr := simp)]
theorem coe_toEquiv_symm (f : M ≃* N) : ((f : M ≃ N).symm : N → M) = f.symm 
goal: ⇑(↑f).symm = ⇑f.symm

full_name: MulEquiv.equivLike_inv_eq_symm
code: @[to_additive (attr := simp)]
theorem equivLike_inv_eq_symm (f : M ≃* N) : EquivLike.inv f = f.symm 
goal: EquivLike.inv f = ⇑f.symm

full_name: AddEquiv.equivLike_neg_eq_symm
code: @[to_additive (attr := simp)]
theorem equivLike_inv_eq_symm (f : M ≃* N) : EquivLike.inv f = f.symm 
goal: EquivLike.inv f = ⇑f.symm

full_name: MulEquiv.Simps.symm_apply
code: /-- See Note [custom simps projection] -/
@[to_additive "See Note [custom simps projection]"] -- this comment fixes the syntax highlighting "
def Simps.symm_apply (e : M ≃* N) : N → M 
goal: N → M

full_name: AddEquiv.Simps.symm_apply
code: /-- See Note [custom simps projection] -/
@[to_additive "See Note [custom simps projection]"] -- this comment fixes the syntax highlighting "
def Simps.symm_apply (e : M ≃* N) : N → M 
goal: N → M

full_name: AddEquiv.toEquiv_symm
code: @[to_additive (attr := simp)]
theorem toEquiv_symm (f : M ≃* N) : (f.symm : N ≃ M) = (f : M ≃ N).symm 
goal: ↑f.symm = (↑f).symm

full_name: MulEquiv.toEquiv_symm
code: @[to_additive (attr := simp)]
theorem toEquiv_symm (f : M ≃* N) : (f.symm : N ≃ M) = (f : M ≃ N).symm 
goal: ↑f.symm = (↑f).symm

full_name: MulEquiv.coe_mk
code: @[to_additive (attr := simp)]
theorem coe_mk (f : M ≃ N) (hf : ∀ x y, f (x * y) = f x * f y) : (mk f hf : M → N) = f 
goal: ⇑{ toEquiv := f, map_mul' := hf } = ⇑f

full_name: AddEquiv.coe_mk
code: @[to_additive (attr := simp)]
theorem coe_mk (f : M ≃ N) (hf : ∀ x y, f (x * y) = f x * f y) : (mk f hf : M → N) = f 
goal: ⇑{ toEquiv := f, map_add' := hf } = ⇑f

full_name: AddEquiv.symm_symm
code: @[to_additive (attr := simp)]
theorem symm_symm (f : M ≃* N) : f.symm.symm = f 
goal: f.symm.symm = f

full_name: MulEquiv.symm_symm
code: @[to_additive (attr := simp)]
theorem symm_symm (f : M ≃* N) : f.symm.symm = f 
goal: f.symm.symm = f

full_name: MulEquiv.symm_bijective
code: @[to_additive]
theorem symm_bijective : Function.Bijective (symm : (M ≃* N) → N ≃* M) 
goal: Function.Bijective MulEquiv.symm

full_name: AddEquiv.symm_bijective
code: @[to_additive]
theorem symm_bijective : Function.Bijective (symm : (M ≃* N) → N ≃* M) 
goal: Function.Bijective AddEquiv.symm

full_name: MulEquiv.symm_mk
code: @[to_additive (attr := simp)]
theorem symm_mk (f : M ≃ N) (h) :
    (MulEquiv.mk f h).symm = ⟨f.symm, (MulEquiv.mk f h).symm_map_mul⟩ 
goal: { toEquiv := f, map_mul' := h }.symm = { toEquiv := f.symm, map_mul' := ⋯ }

full_name: AddEquiv.symm_mk
code: @[to_additive (attr := simp)]
theorem symm_mk (f : M ≃ N) (h) :
    (MulEquiv.mk f h).symm = ⟨f.symm, (MulEquiv.mk f h).symm_map_mul⟩ 
goal: { toEquiv := f, map_add' := h }.symm = { toEquiv := f.symm, map_add' := ⋯ }

full_name: MulEquiv.refl_symm
code: @[to_additive (attr := simp)]
theorem refl_symm : (refl M).symm = refl M 
goal: (MulEquiv.refl M).symm = MulEquiv.refl M

full_name: AddEquiv.refl_symm
code: @[to_additive (attr := simp)]
theorem refl_symm : (refl M).symm = refl M 
goal: (AddEquiv.refl M).symm = AddEquiv.refl M

full_name: AddEquiv.trans
code: /-- Transitivity of multiplication-preserving isomorphisms -/
@[to_additive (attr := trans) "Transitivity of addition-preserving isomorphisms"]
def trans (h1 : M ≃* N) (h2 : N ≃* P) : M ≃* P 
goal: M ≃+ P

full_name: MulEquiv.trans
code: /-- Transitivity of multiplication-preserving isomorphisms -/
@[to_additive (attr := trans) "Transitivity of addition-preserving isomorphisms"]
def trans (h1 : M ≃* N) (h2 : N ≃* P) : M ≃* P 
goal: M ≃* P

full_name: AddEquiv.apply_symm_apply
code: /-- `e.symm` is a right inverse of `e`, written as `e (e.symm y) = y`. -/
@[to_additive (attr := simp) "`e.symm` is a right inverse of `e`, written as `e (e.symm y) = y`."]
theorem apply_symm_apply (e : M ≃* N) (y : N) : e (e.symm y) = y 
goal: e (e.symm y) = y

full_name: MulEquiv.apply_symm_apply
code: /-- `e.symm` is a right inverse of `e`, written as `e (e.symm y) = y`. -/
@[to_additive (attr := simp) "`e.symm` is a right inverse of `e`, written as `e (e.symm y) = y`."]
theorem apply_symm_apply (e : M ≃* N) (y : N) : e (e.symm y) = y 
goal: e (e.symm y) = y

full_name: MulEquiv.symm_apply_apply
code: /-- `e.symm` is a left inverse of `e`, written as `e.symm (e y) = y`. -/
@[to_additive (attr := simp) "`e.symm` is a left inverse of `e`, written as `e.symm (e y) = y`."]
theorem symm_apply_apply (e : M ≃* N) (x : M) : e.symm (e x) = x 
goal: e.symm (e x) = x

full_name: AddEquiv.symm_apply_apply
code: /-- `e.symm` is a left inverse of `e`, written as `e.symm (e y) = y`. -/
@[to_additive (attr := simp) "`e.symm` is a left inverse of `e`, written as `e.symm (e y) = y`."]
theorem symm_apply_apply (e : M ≃* N) (x : M) : e.symm (e x) = x 
goal: e.symm (e x) = x

full_name: MulEquiv.symm_comp_self
code: @[to_additive (attr := simp)]
theorem symm_comp_self (e : M ≃* N) : e.symm ∘ e = id 
goal: ⇑e.symm ∘ ⇑e = id

full_name: AddEquiv.symm_comp_self
code: @[to_additive (attr := simp)]
theorem symm_comp_self (e : M ≃* N) : e.symm ∘ e = id 
goal: ⇑e.symm ∘ ⇑e = id

full_name: MulEquiv.self_comp_symm
code: @[to_additive (attr := simp)]
theorem self_comp_symm (e : M ≃* N) : e ∘ e.symm = id 
goal: ⇑e ∘ ⇑e.symm = id

full_name: AddEquiv.self_comp_symm
code: @[to_additive (attr := simp)]
theorem self_comp_symm (e : M ≃* N) : e ∘ e.symm = id 
goal: ⇑e ∘ ⇑e.symm = id

full_name: MulEquiv.coe_refl
code: @[to_additive (attr := simp)]
theorem coe_refl : ↑(refl M) = id 
goal: ⇑(MulEquiv.refl M) = id

full_name: AddEquiv.coe_refl
code: @[to_additive (attr := simp)]
theorem coe_refl : ↑(refl M) = id 
goal: ⇑(AddEquiv.refl M) = id

full_name: MulEquiv.refl_apply
code: @[to_additive (attr := simp)]
theorem refl_apply (m : M) : refl M m = m 
goal: (MulEquiv.refl M) m = m

full_name: AddEquiv.refl_apply
code: @[to_additive (attr := simp)]
theorem refl_apply (m : M) : refl M m = m 
goal: (AddEquiv.refl M) m = m

full_name: MulEquiv.coe_trans
code: @[to_additive (attr := simp)]
theorem coe_trans (e₁ : M ≃* N) (e₂ : N ≃* P) : ↑(e₁.trans e₂) = e₂ ∘ e₁ 
goal: ⇑(e₁.trans e₂) = ⇑e₂ ∘ ⇑e₁

full_name: AddEquiv.coe_trans
code: @[to_additive (attr := simp)]
theorem coe_trans (e₁ : M ≃* N) (e₂ : N ≃* P) : ↑(e₁.trans e₂) = e₂ ∘ e₁ 
goal: ⇑(e₁.trans e₂) = ⇑e₂ ∘ ⇑e₁

full_name: MulEquiv.trans_apply
code: @[to_additive (attr := simp)]
theorem trans_apply (e₁ : M ≃* N) (e₂ : N ≃* P) (m : M) : e₁.trans e₂ m = e₂ (e₁ m) 
goal: (e₁.trans e₂) m = e₂ (e₁ m)

full_name: AddEquiv.trans_apply
code: @[to_additive (attr := simp)]
theorem trans_apply (e₁ : M ≃* N) (e₂ : N ≃* P) (m : M) : e₁.trans e₂ m = e₂ (e₁ m) 
goal: (e₁.trans e₂) m = e₂ (e₁ m)

full_name: MulEquiv.symm_trans_apply
code: @[to_additive (attr := simp)]
theorem symm_trans_apply (e₁ : M ≃* N) (e₂ : N ≃* P) (p : P) :
    (e₁.trans e₂).symm p = e₁.symm (e₂.symm p) 
goal: (e₁.trans e₂).symm p = e₁.symm (e₂.symm p)

full_name: AddEquiv.symm_trans_apply
code: @[to_additive (attr := simp)]
theorem symm_trans_apply (e₁ : M ≃* N) (e₂ : N ≃* P) (p : P) :
    (e₁.trans e₂).symm p = e₁.symm (e₂.symm p) 
goal: (e₁.trans e₂).symm p = e₁.symm (e₂.symm p)

full_name: MulEquiv.apply_eq_iff_eq
code: @[to_additive]
theorem apply_eq_iff_eq (e : M ≃* N) {x y : M} : e x = e y ↔ x = y 
goal: e x = e y ↔ x = y

full_name: AddEquiv.apply_eq_iff_eq
code: @[to_additive]
theorem apply_eq_iff_eq (e : M ≃* N) {x y : M} : e x = e y ↔ x = y 
goal: e x = e y ↔ x = y

full_name: MulEquiv.apply_eq_iff_symm_apply
code: @[to_additive]
theorem apply_eq_iff_symm_apply (e : M ≃* N) {x : M} {y : N} : e x = y ↔ x = e.symm y 
goal: e x = y ↔ x = e.symm y

full_name: AddEquiv.apply_eq_iff_symm_apply
code: @[to_additive]
theorem apply_eq_iff_symm_apply (e : M ≃* N) {x : M} {y : N} : e x = y ↔ x = e.symm y 
goal: e x = y ↔ x = e.symm y

full_name: MulEquiv.symm_apply_eq
code: @[to_additive]
theorem symm_apply_eq (e : M ≃* N) {x y} : e.symm x = y ↔ x = e y 
goal: e.symm x = y ↔ x = e y

full_name: AddEquiv.symm_apply_eq
code: @[to_additive]
theorem symm_apply_eq (e : M ≃* N) {x y} : e.symm x = y ↔ x = e y 
goal: e.symm x = y ↔ x = e y

full_name: MulEquiv.eq_symm_apply
code: @[to_additive]
theorem eq_symm_apply (e : M ≃* N) {x y} : y = e.symm x ↔ e y = x 
goal: y = e.symm x ↔ e y = x

full_name: AddEquiv.eq_symm_apply
code: @[to_additive]
theorem eq_symm_apply (e : M ≃* N) {x y} : y = e.symm x ↔ e y = x 
goal: y = e.symm x ↔ e y = x

full_name: MulEquiv.eq_comp_symm
code: @[to_additive]
theorem eq_comp_symm {α : Type*} (e : M ≃* N) (f : N → α) (g : M → α) :
    f = g ∘ e.symm ↔ f ∘ e = g 
goal: f = g ∘ ⇑e.symm ↔ f ∘ ⇑e = g

full_name: AddEquiv.eq_comp_symm
code: @[to_additive]
theorem eq_comp_symm {α : Type*} (e : M ≃* N) (f : N → α) (g : M → α) :
    f = g ∘ e.symm ↔ f ∘ e = g 
goal: f = g ∘ ⇑e.symm ↔ f ∘ ⇑e = g

full_name: MulEquiv.comp_symm_eq
code: @[to_additive]
theorem comp_symm_eq {α : Type*} (e : M ≃* N) (f : N → α) (g : M → α) :
    g ∘ e.symm = f ↔ g = f ∘ e 
goal: g ∘ ⇑e.symm = f ↔ g = f ∘ ⇑e

full_name: AddEquiv.comp_symm_eq
code: @[to_additive]
theorem comp_symm_eq {α : Type*} (e : M ≃* N) (f : N → α) (g : M → α) :
    g ∘ e.symm = f ↔ g = f ∘ e 
goal: g ∘ ⇑e.symm = f ↔ g = f ∘ ⇑e

full_name: AddEquiv.eq_symm_comp
code: @[to_additive]
theorem eq_symm_comp {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) :
    f = e.symm ∘ g ↔ e ∘ f = g 
goal: f = ⇑e.symm ∘ g ↔ ⇑e ∘ f = g

full_name: MulEquiv.eq_symm_comp
code: @[to_additive]
theorem eq_symm_comp {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) :
    f = e.symm ∘ g ↔ e ∘ f = g 
goal: f = ⇑e.symm ∘ g ↔ ⇑e ∘ f = g

full_name: MulEquiv.symm_comp_eq
code: @[to_additive]
theorem symm_comp_eq {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) :
    e.symm ∘ g = f ↔ g = e ∘ f 
goal: ⇑e.symm ∘ g = f ↔ g = ⇑e ∘ f

full_name: AddEquiv.symm_comp_eq
code: @[to_additive]
theorem symm_comp_eq {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) :
    e.symm ∘ g = f ↔ g = e ∘ f 
goal: ⇑e.symm ∘ g = f ↔ g = ⇑e ∘ f

full_name: MulEquiv.symm_trans_self
code: @[to_additive (attr := simp)]
theorem symm_trans_self (e : M ≃* N) : e.symm.trans e = refl N 
goal: e.symm.trans e = MulEquiv.refl N

full_name: AddEquiv.symm_trans_self
code: @[to_additive (attr := simp)]
theorem symm_trans_self (e : M ≃* N) : e.symm.trans e = refl N 
goal: e.symm.trans e = AddEquiv.refl N

full_name: MulEquiv.self_trans_symm
code: @[to_additive (attr := simp)]
theorem self_trans_symm (e : M ≃* N) : e.trans e.symm = refl M 
goal: e.trans e.symm = MulEquiv.refl M

full_name: AddEquiv.self_trans_symm
code: @[to_additive (attr := simp)]
theorem self_trans_symm (e : M ≃* N) : e.trans e.symm = refl M 
goal: e.trans e.symm = AddEquiv.refl M

full_name: MulEquiv.ext
code: /-- Two multiplicative isomorphisms agree if they are defined by the
same underlying function. -/
@[to_additive (attr := ext)
  "Two additive isomorphisms agree if they are defined by the same underlying function."]
theorem ext {f g : MulEquiv M N} (h : ∀ x, f x = g x) : f = g 
goal: f = g

full_name: AddEquiv.ext
code: /-- Two multiplicative isomorphisms agree if they are defined by the
same underlying function. -/
@[to_additive (attr := ext)
  "Two additive isomorphisms agree if they are defined by the same underlying function."]
theorem ext {f g : MulEquiv M N} (h : ∀ x, f x = g x) : f = g 
goal: f = g

full_name: MulEquiv.ext_iff
code: @[to_additive]
theorem ext_iff {f g : MulEquiv M N} : f = g ↔ ∀ x, f x = g x 
goal: f = g ↔ ∀ (x : M), f x = g x

full_name: AddEquiv.ext_iff
code: @[to_additive]
theorem ext_iff {f g : MulEquiv M N} : f = g ↔ ∀ x, f x = g x 
goal: f = g ↔ ∀ (x : M), f x = g x

full_name: MulEquiv.mk_coe
code: @[to_additive (attr := simp)]
theorem mk_coe (e : M ≃* N) (e' h₁ h₂ h₃) : (⟨⟨e, e', h₁, h₂⟩, h₃⟩ : M ≃* N) = e 
goal: { toFun := ⇑e, invFun := e', left_inv := h₁, right_inv := h₂, map_mul' := h₃ } = e

full_name: AddEquiv.mk_coe
code: @[to_additive (attr := simp)]
theorem mk_coe (e : M ≃* N) (e' h₁ h₂ h₃) : (⟨⟨e, e', h₁, h₂⟩, h₃⟩ : M ≃* N) = e 
goal: { toFun := ⇑e, invFun := e', left_inv := h₁, right_inv := h₂, map_add' := h₃ } = e

full_name: AddEquiv.mk_coe'
code: @[to_additive (attr := simp)]
theorem mk_coe' (e : M ≃* N) (f h₁ h₂ h₃) : (MulEquiv.mk ⟨f, e, h₁, h₂⟩ h₃ : N ≃* M) = e.symm 
goal: { toFun := f, invFun := ⇑e, left_inv := h₁, right_inv := h₂, map_add' := h₃ } = e.symm

full_name: MulEquiv.mk_coe'
code: @[to_additive (attr := simp)]
theorem mk_coe' (e : M ≃* N) (f h₁ h₂ h₃) : (MulEquiv.mk ⟨f, e, h₁, h₂⟩ h₃ : N ≃* M) = e.symm 
goal: { toFun := f, invFun := ⇑e, left_inv := h₁, right_inv := h₂, map_mul' := h₃ } = e.symm

full_name: AddEquiv.congr_arg
code: @[to_additive]
protected theorem congr_arg {f : MulEquiv M N} {x x' : M} : x = x' → f x = f x' 
goal: x = x' → f x = f x'

full_name: MulEquiv.congr_arg
code: @[to_additive]
protected theorem congr_arg {f : MulEquiv M N} {x x' : M} : x = x' → f x = f x' 
goal: x = x' → f x = f x'

full_name: MulEquiv.congr_fun
code: @[to_additive]
protected theorem congr_fun {f g : MulEquiv M N} (h : f = g) (x : M) : f x = g x 
goal: f x = g x

full_name: AddEquiv.congr_fun
code: @[to_additive]
protected theorem congr_fun {f g : MulEquiv M N} (h : f = g) (x : M) : f x = g x 
goal: f x = g x

full_name: AddEquiv.addEquivOfUnique
code: /-- The `MulEquiv` between two monoids with a unique element. -/
@[to_additive "The `AddEquiv` between two `AddMonoid`s with a unique element."]
def mulEquivOfUnique {M N} [Unique M] [Unique N] [Mul M] [Mul N] : M ≃* N 
goal: M ≃+ N

full_name: MulEquiv.mulEquivOfUnique
code: /-- The `MulEquiv` between two monoids with a unique element. -/
@[to_additive "The `AddEquiv` between two `AddMonoid`s with a unique element."]
def mulEquivOfUnique {M N} [Unique M] [Unique N] [Mul M] [Mul N] : M ≃* N 
goal: M ≃* N

full_name: MulEquiv.instUnique
code: /-- There is a unique monoid homomorphism between two monoids with a unique element. -/
@[to_additive "There is a unique additive monoid homomorphism between two additive monoids with
  a unique element."]
instance {M N} [Unique M] [Unique N] [Mul M] [Mul N] : Unique (M ≃* N) 
goal: Unique (M ≃* N)

full_name: AddEquiv.instUnique
code: /-- There is a unique monoid homomorphism between two monoids with a unique element. -/
@[to_additive "There is a unique additive monoid homomorphism between two additive monoids with
  a unique element."]
instance {M N} [Unique M] [Unique N] [Mul M] [Mul N] : Unique (M ≃* N) 
goal: Unique (M ≃+ N)

full_name: MulEquiv.coe_monoidHom_refl
code: @[to_additive]
theorem coe_monoidHom_refl : (refl M : M →* M) = MonoidHom.id M 
goal: ↑(MulEquiv.refl M) = MonoidHom.id M

full_name: AddEquiv.coe_addMonoidHom_refl
code: @[to_additive]
theorem coe_monoidHom_refl : (refl M : M →* M) = MonoidHom.id M 
goal: ↑(AddEquiv.refl M) = AddMonoidHom.id M

full_name: MulEquiv.coe_monoidHom_trans
code: @[to_additive]
lemma coe_monoidHom_trans (e₁ : M ≃* N) (e₂ : N ≃* P) :
    (e₁.trans e₂ : M →* P) = (e₂ : N →* P).comp ↑e₁ 
goal: ↑(e₁.trans e₂) = (↑e₂).comp ↑e₁

full_name: AddEquiv.coe_addMonoidHom_trans
code: @[to_additive]
lemma coe_monoidHom_trans (e₁ : M ≃* N) (e₂ : N ≃* P) :
    (e₁.trans e₂ : M →* P) = (e₂ : N →* P).comp ↑e₁ 
goal: ↑(e₁.trans e₂) = (↑e₂).comp ↑e₁

full_name: AddEquiv.coe_addMonoidHom_comp_coe_addMonoidHom_symm
code: @[to_additive (attr := simp)]
lemma coe_monoidHom_comp_coe_monoidHom_symm (e : M ≃* N) :
    (e : M →* N).comp e.symm = MonoidHom.id _ 
goal: (↑e).comp ↑e.symm = AddMonoidHom.id N

full_name: MulEquiv.coe_monoidHom_comp_coe_monoidHom_symm
code: @[to_additive (attr := simp)]
lemma coe_monoidHom_comp_coe_monoidHom_symm (e : M ≃* N) :
    (e : M →* N).comp e.symm = MonoidHom.id _ 
goal: (↑e).comp ↑e.symm = MonoidHom.id N

full_name: AddEquiv.coe_addMonoidHom_symm_comp_coe_addMonoidHom
code: @[to_additive (attr := simp)]
lemma coe_monoidHom_symm_comp_coe_monoidHom (e : M ≃* N) :
    (e.symm : N →* M).comp e = MonoidHom.id _ 
goal: (↑e.symm).comp ↑e = AddMonoidHom.id M

full_name: MulEquiv.coe_monoidHom_symm_comp_coe_monoidHom
code: @[to_additive (attr := simp)]
lemma coe_monoidHom_symm_comp_coe_monoidHom (e : M ≃* N) :
    (e.symm : N →* M).comp e = MonoidHom.id _ 
goal: (↑e.symm).comp ↑e = MonoidHom.id M

full_name: AddEquiv.comp_left_injective
code: @[to_additive]
lemma comp_left_injective (e : M ≃* N) : Injective fun f : N →* P ↦ f.comp (e : M →* N) 
goal: Function.Injective fun f => f.comp ↑e

full_name: MulEquiv.comp_left_injective
code: @[to_additive]
lemma comp_left_injective (e : M ≃* N) : Injective fun f : N →* P ↦ f.comp (e : M →* N) 
goal: Function.Injective fun f => f.comp ↑e

full_name: MulEquiv.comp_right_injective
code: @[to_additive]
lemma comp_right_injective (e : M ≃* N) : Injective fun f : P →* M ↦ (e : M →* N).comp f 
goal: Function.Injective fun f => (↑e).comp f

full_name: AddEquiv.comp_right_injective
code: @[to_additive]
lemma comp_right_injective (e : M ≃* N) : Injective fun f : P →* M ↦ (e : M →* N).comp f 
goal: Function.Injective fun f => (↑e).comp f

full_name: MulEquiv.map_one
code: /-- A multiplicative isomorphism of monoids sends `1` to `1` (and is hence a monoid isomorphism). -/
@[to_additive
  "An additive isomorphism of additive monoids sends `0` to `0`
  (and is hence an additive monoid isomorphism)."]
protected theorem map_one (h : M ≃* N) : h 1 = 1 
goal: h 1 = 1

full_name: AddEquiv.map_zero
code: /-- A multiplicative isomorphism of monoids sends `1` to `1` (and is hence a monoid isomorphism). -/
@[to_additive
  "An additive isomorphism of additive monoids sends `0` to `0`
  (and is hence an additive monoid isomorphism)."]
protected theorem map_one (h : M ≃* N) : h 1 = 1 
goal: h 0 = 0

full_name: MulEquiv.map_eq_one_iff
code: @[to_additive]
protected theorem map_eq_one_iff (h : M ≃* N) {x : M} : h x = 1 ↔ x = 1 
goal: h x = 1 ↔ x = 1

full_name: AddEquiv.map_eq_zero_iff
code: @[to_additive]
protected theorem map_eq_one_iff (h : M ≃* N) {x : M} : h x = 1 ↔ x = 1 
goal: h x = 0 ↔ x = 0

full_name: AddEquiv.map_ne_zero_iff
code: @[to_additive]
theorem map_ne_one_iff (h : M ≃* N) {x : M} : h x ≠ 1 ↔ x ≠ 1 
goal: h x ≠ 0 ↔ x ≠ 0

full_name: MulEquiv.map_ne_one_iff
code: @[to_additive]
theorem map_ne_one_iff (h : M ≃* N) {x : M} : h x ≠ 1 ↔ x ≠ 1 
goal: h x ≠ 1 ↔ x ≠ 1

full_name: AddEquiv.ofBijective
code: /-- A bijective `Semigroup` homomorphism is an isomorphism -/
@[to_additive (attr := simps! apply) "A bijective `AddSemigroup` homomorphism is an isomorphism"]
noncomputable def ofBijective {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N]
    (f : F) (hf : Bijective f) : M ≃* N 
goal: M ≃+ N

full_name: MulEquiv.ofBijective
code: /-- A bijective `Semigroup` homomorphism is an isomorphism -/
@[to_additive (attr := simps! apply) "A bijective `AddSemigroup` homomorphism is an isomorphism"]
noncomputable def ofBijective {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N]
    (f : F) (hf : Bijective f) : M ≃* N 
goal: M ≃* N

full_name: MulEquiv.ofBijective_apply
code: /-- A bijective `Semigroup` homomorphism is an isomorphism -/
@[to_additive (attr := simps! apply) "A bijective `AddSemigroup` homomorphism is an isomorphism"]
noncomputable def ofBijective {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N]
    (f : F) (hf : Bijective f) : M ≃* N 
goal: (MulEquiv.ofBijective f hf) a = f a

full_name: AddEquiv.ofBijective_apply
code: /-- A bijective `Semigroup` homomorphism is an isomorphism -/
@[to_additive (attr := simps! apply) "A bijective `AddSemigroup` homomorphism is an isomorphism"]
noncomputable def ofBijective {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N]
    (f : F) (hf : Bijective f) : M ≃* N 
goal: (AddEquiv.ofBijective f hf) a = f a

full_name: MulEquiv.ofBijective_apply_symm_apply
code: @[to_additive (attr := simp)]
theorem ofBijective_apply_symm_apply {n : N} (f : M →* N) (hf : Bijective f) :
    f ((ofBijective f hf).symm n) = n 
goal: f ((MulEquiv.ofBijective f hf).symm n) = n

full_name: AddEquiv.ofBijective_apply_symm_apply
code: @[to_additive (attr := simp)]
theorem ofBijective_apply_symm_apply {n : N} (f : M →* N) (hf : Bijective f) :
    f ((ofBijective f hf).symm n) = n 
goal: f ((AddEquiv.ofBijective f hf).symm n) = n

full_name: MulEquiv.toMonoidHom
code: /-- Extract the forward direction of a multiplicative equivalence
as a multiplication-preserving function.
-/
@[to_additive "Extract the forward direction of an additive equivalence
  as an addition-preserving function."]
def toMonoidHom (h : M ≃* N) : M →* N 
goal: M →* N

full_name: AddEquiv.toAddMonoidHom
code: /-- Extract the forward direction of a multiplicative equivalence
as a multiplication-preserving function.
-/
@[to_additive "Extract the forward direction of an additive equivalence
  as an addition-preserving function."]
def toMonoidHom (h : M ≃* N) : M →* N 
goal: M →+ N

full_name: AddEquiv.coe_toAddMonoidHom
code: @[to_additive (attr := simp)]
theorem coe_toMonoidHom (e : M ≃* N) : ⇑e.toMonoidHom = e 
goal: ⇑e.toAddMonoidHom = ⇑e

full_name: MulEquiv.coe_toMonoidHom
code: @[to_additive (attr := simp)]
theorem coe_toMonoidHom (e : M ≃* N) : ⇑e.toMonoidHom = e 
goal: ⇑e.toMonoidHom = ⇑e

full_name: MulEquiv.toMonoidHom_eq_coe
code: @[to_additive (attr := simp)]
theorem toMonoidHom_eq_coe (f : M ≃* N) : f.toMonoidHom = (f : M →* N) 
goal: f.toMonoidHom = ↑f

full_name: AddEquiv.toAddMonoidHom_eq_coe
code: @[to_additive (attr := simp)]
theorem toMonoidHom_eq_coe (f : M ≃* N) : f.toMonoidHom = (f : M →* N) 
goal: f.toAddMonoidHom = ↑f

full_name: MulEquiv.toMonoidHom_injective
code: @[to_additive]
theorem toMonoidHom_injective : Injective (toMonoidHom : M ≃* N → M →* N) 
goal: Function.Injective MulEquiv.toMonoidHom

full_name: AddEquiv.toAddMonoidHom_injective
code: @[to_additive]
theorem toMonoidHom_injective : Injective (toMonoidHom : M ≃* N → M →* N) 
goal: Function.Injective AddEquiv.toAddMonoidHom

full_name: MulEquiv.arrowCongr
code: /-- A multiplicative analogue of `Equiv.arrowCongr`,
where the equivalence between the targets is multiplicative.
-/
@[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`,
  where the equivalence between the targets is additive."]
def arrowCongr {M N P Q : Type*} [Mul P] [Mul Q] (f : M ≃ N) (g : P ≃* Q) :
    (M → P) ≃* (N → Q) 
goal: (M → P) ≃* (N → Q)

full_name: MulEquiv.arrowCongr_apply
code: /-- A multiplicative analogue of `Equiv.arrowCongr`,
where the equivalence between the targets is multiplicative.
-/
@[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`,
  where the equivalence between the targets is additive."]
def arrowCongr {M N P Q : Type*} [Mul P] [Mul Q] (f : M ≃ N) (g : P ≃* Q) :
    (M → P) ≃* (N → Q) 
goal: (MulEquiv.arrowCongr f g) h n = g (h (f.symm n))

full_name: AddEquiv.arrowCongr
code: /-- A multiplicative analogue of `Equiv.arrowCongr`,
where the equivalence between the targets is multiplicative.
-/
@[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`,
  where the equivalence between the targets is additive."]
def arrowCongr {M N P Q : Type*} [Mul P] [Mul Q] (f : M ≃ N) (g : P ≃* Q) :
    (M → P) ≃* (N → Q) 
goal: (M → P) ≃+ (N → Q)

full_name: AddEquiv.arrowCongr_apply
code: /-- A multiplicative analogue of `Equiv.arrowCongr`,
where the equivalence between the targets is multiplicative.
-/
@[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`,
  where the equivalence between the targets is additive."]
def arrowCongr {M N P Q : Type*} [Mul P] [Mul Q] (f : M ≃ N) (g : P ≃* Q) :
    (M → P) ≃* (N → Q) 
goal: (AddEquiv.arrowCongr f g) h n = g (h (f.symm n))

full_name: AddEquiv.addMonoidHomCongr
code: /-- A multiplicative analogue of `Equiv.arrowCongr`,
for multiplicative maps from a monoid to a commutative monoid.
-/
@[to_additive (attr := simps apply)
  "An additive analogue of `Equiv.arrowCongr`,
  for additive maps from an additive monoid to a commutative additive monoid."]
-- Porting note: @[simps apply] removed because it was making a lemma which
-- wasn't in simp normal form.
def monoidHomCongr {M N P Q} [MulOneClass M] [MulOneClass N] [CommMonoid P] [CommMonoid Q]
    (f : M ≃* N) (g : P ≃* Q) : (M →* P) ≃* (N →* Q) 
goal: (M →+ P) ≃+ (N →+ Q)

full_name: MulEquiv.monoidHomCongr
code: /-- A multiplicative analogue of `Equiv.arrowCongr`,
for multiplicative maps from a monoid to a commutative monoid.
-/
@[to_additive (attr := simps apply)
  "An additive analogue of `Equiv.arrowCongr`,
  for additive maps from an additive monoid to a commutative additive monoid."]
-- Porting note: @[simps apply] removed because it was making a lemma which
-- wasn't in simp normal form.
def monoidHomCongr {M N P Q} [MulOneClass M] [MulOneClass N] [CommMonoid P] [CommMonoid Q]
    (f : M ≃* N) (g : P ≃* Q) : (M →* P) ≃* (N →* Q) 
goal: (M →* P) ≃* (N →* Q)

full_name: MulEquiv.monoidHomCongr_apply
code: /-- A multiplicative analogue of `Equiv.arrowCongr`,
for multiplicative maps from a monoid to a commutative monoid.
-/
@[to_additive (attr := simps apply)
  "An additive analogue of `Equiv.arrowCongr`,
  for additive maps from an additive monoid to a commutative additive monoid."]
-- Porting note: @[simps apply] removed because it was making a lemma which
-- wasn't in simp normal form.
def monoidHomCongr {M N P Q} [MulOneClass M] [MulOneClass N] [CommMonoid P] [CommMonoid Q]
    (f : M ≃* N) (g : P ≃* Q) : (M →* P) ≃* (N →* Q) 
goal: (f.monoidHomCongr g) h = g.toMonoidHom.comp (h.comp f.symm.toMonoidHom)

full_name: AddEquiv.addMonoidHomCongr_apply
code: /-- A multiplicative analogue of `Equiv.arrowCongr`,
for multiplicative maps from a monoid to a commutative monoid.
-/
@[to_additive (attr := simps apply)
  "An additive analogue of `Equiv.arrowCongr`,
  for additive maps from an additive monoid to a commutative additive monoid."]
-- Porting note: @[simps apply] removed because it was making a lemma which
-- wasn't in simp normal form.
def monoidHomCongr {M N P Q} [MulOneClass M] [MulOneClass N] [CommMonoid P] [CommMonoid Q]
    (f : M ≃* N) (g : P ≃* Q) : (M →* P) ≃* (N →* Q) 
goal: (f.addMonoidHomCongr g) h = g.toAddMonoidHom.comp (h.comp f.symm.toAddMonoidHom)

full_name: AddEquiv.piCongrRight
code: /-- A family of multiplicative equivalences `Π j, (Ms j ≃* Ns j)` generates a
multiplicative equivalence between `Π j, Ms j` and `Π j, Ns j`.

This is the `MulEquiv` version of `Equiv.piCongrRight`, and the dependent version of
`MulEquiv.arrowCongr`.
-/
@[to_additive (attr := simps apply)
  "A family of additive equivalences `Π j, (Ms j ≃+ Ns j)`
  generates an additive equivalence between `Π j, Ms j` and `Π j, Ns j`.

  This is the `AddEquiv` version of `Equiv.piCongrRight`, and the dependent version of
  `AddEquiv.arrowCongr`."]
def piCongrRight {η : Type*} {Ms Ns : η → Type*} [∀ j, Mul (Ms j)] [∀ j, Mul (Ns j)]
    (es : ∀ j, Ms j ≃* Ns j) : (∀ j, Ms j) ≃* ∀ j, Ns j 
goal: ((j : η) → Ms j) ≃+ ((j : η) → Ns j)

full_name: MulEquiv.piCongrRight
code: /-- A family of multiplicative equivalences `Π j, (Ms j ≃* Ns j)` generates a
multiplicative equivalence between `Π j, Ms j` and `Π j, Ns j`.

This is the `MulEquiv` version of `Equiv.piCongrRight`, and the dependent version of
`MulEquiv.arrowCongr`.
-/
@[to_additive (attr := simps apply)
  "A family of additive equivalences `Π j, (Ms j ≃+ Ns j)`
  generates an additive equivalence between `Π j, Ms j` and `Π j, Ns j`.

  This is the `AddEquiv` version of `Equiv.piCongrRight`, and the dependent version of
  `AddEquiv.arrowCongr`."]
def piCongrRight {η : Type*} {Ms Ns : η → Type*} [∀ j, Mul (Ms j)] [∀ j, Mul (Ns j)]
    (es : ∀ j, Ms j ≃* Ns j) : (∀ j, Ms j) ≃* ∀ j, Ns j 
goal: ((j : η) → Ms j) ≃* ((j : η) → Ns j)

full_name: MulEquiv.piCongrRight_apply
code: /-- A family of multiplicative equivalences `Π j, (Ms j ≃* Ns j)` generates a
multiplicative equivalence between `Π j, Ms j` and `Π j, Ns j`.

This is the `MulEquiv` version of `Equiv.piCongrRight`, and the dependent version of
`MulEquiv.arrowCongr`.
-/
@[to_additive (attr := simps apply)
  "A family of additive equivalences `Π j, (Ms j ≃+ Ns j)`
  generates an additive equivalence between `Π j, Ms j` and `Π j, Ns j`.

  This is the `AddEquiv` version of `Equiv.piCongrRight`, and the dependent version of
  `AddEquiv.arrowCongr`."]
def piCongrRight {η : Type*} {Ms Ns : η → Type*} [∀ j, Mul (Ms j)] [∀ j, Mul (Ns j)]
    (es : ∀ j, Ms j ≃* Ns j) : (∀ j, Ms j) ≃* ∀ j, Ns j 
goal: (MulEquiv.piCongrRight es) x j = (es j) (x j)

full_name: AddEquiv.piCongrRight_apply
code: /-- A family of multiplicative equivalences `Π j, (Ms j ≃* Ns j)` generates a
multiplicative equivalence between `Π j, Ms j` and `Π j, Ns j`.

This is the `MulEquiv` version of `Equiv.piCongrRight`, and the dependent version of
`MulEquiv.arrowCongr`.
-/
@[to_additive (attr := simps apply)
  "A family of additive equivalences `Π j, (Ms j ≃+ Ns j)`
  generates an additive equivalence between `Π j, Ms j` and `Π j, Ns j`.

  This is the `AddEquiv` version of `Equiv.piCongrRight`, and the dependent version of
  `AddEquiv.arrowCongr`."]
def piCongrRight {η : Type*} {Ms Ns : η → Type*} [∀ j, Mul (Ms j)] [∀ j, Mul (Ns j)]
    (es : ∀ j, Ms j ≃* Ns j) : (∀ j, Ms j) ≃* ∀ j, Ns j 
goal: (AddEquiv.piCongrRight es) x j = (es j) (x j)

full_name: MulEquiv.piCongrRight_refl
code: @[to_additive (attr := simp)]
theorem piCongrRight_refl {η : Type*} {Ms : η → Type*} [∀ j, Mul (Ms j)] :
    (piCongrRight fun j => MulEquiv.refl (Ms j)) = MulEquiv.refl _ 
goal: (MulEquiv.piCongrRight fun j => MulEquiv.refl (Ms j)) = MulEquiv.refl ((j : η) → Ms j)

full_name: AddEquiv.piCongrRight_refl
code: @[to_additive (attr := simp)]
theorem piCongrRight_refl {η : Type*} {Ms : η → Type*} [∀ j, Mul (Ms j)] :
    (piCongrRight fun j => MulEquiv.refl (Ms j)) = MulEquiv.refl _ 
goal: (AddEquiv.piCongrRight fun j => AddEquiv.refl (Ms j)) = AddEquiv.refl ((j : η) → Ms j)

full_name: MulEquiv.piCongrRight_symm
code: @[to_additive (attr := simp)]
theorem piCongrRight_symm {η : Type*} {Ms Ns : η → Type*} [∀ j, Mul (Ms j)] [∀ j, Mul (Ns j)]
    (es : ∀ j, Ms j ≃* Ns j) : (piCongrRight es).symm = piCongrRight fun i => (es i).symm 
goal: (MulEquiv.piCongrRight es).symm = MulEquiv.piCongrRight fun i => (es i).symm

full_name: AddEquiv.piCongrRight_symm
code: @[to_additive (attr := simp)]
theorem piCongrRight_symm {η : Type*} {Ms Ns : η → Type*} [∀ j, Mul (Ms j)] [∀ j, Mul (Ns j)]
    (es : ∀ j, Ms j ≃* Ns j) : (piCongrRight es).symm = piCongrRight fun i => (es i).symm 
goal: (AddEquiv.piCongrRight es).symm = AddEquiv.piCongrRight fun i => (es i).symm

full_name: AddEquiv.piCongrRight_trans
code: @[to_additive (attr := simp)]
theorem piCongrRight_trans {η : Type*} {Ms Ns Ps : η → Type*} [∀ j, Mul (Ms j)]
    [∀ j, Mul (Ns j)] [∀ j, Mul (Ps j)] (es : ∀ j, Ms j ≃* Ns j) (fs : ∀ j, Ns j ≃* Ps j) :
    (piCongrRight es).trans (piCongrRight fs) = piCongrRight fun i => (es i).trans (fs i) 
goal: (AddEquiv.piCongrRight es).trans (AddEquiv.piCongrRight fs) = AddEquiv.piCongrRight fun i => (es i).trans (fs i)

full_name: MulEquiv.piCongrRight_trans
code: @[to_additive (attr := simp)]
theorem piCongrRight_trans {η : Type*} {Ms Ns Ps : η → Type*} [∀ j, Mul (Ms j)]
    [∀ j, Mul (Ns j)] [∀ j, Mul (Ps j)] (es : ∀ j, Ms j ≃* Ns j) (fs : ∀ j, Ns j ≃* Ps j) :
    (piCongrRight es).trans (piCongrRight fs) = piCongrRight fun i => (es i).trans (fs i) 
goal: (MulEquiv.piCongrRight es).trans (MulEquiv.piCongrRight fs) = MulEquiv.piCongrRight fun i => (es i).trans (fs i)

full_name: MulEquiv.piUnique_symm_apply
code: /-- A family indexed by a type with a unique element
is `MulEquiv` to the element at the single index. -/
@[to_additive (attr := simps!)
  "A family indexed by a type with a unique element
  is `AddEquiv` to the element at the single index."]
def piUnique {ι : Type*} (M : ι → Type*) [∀ j, Mul (M j)] [Unique ι] :
    (∀ j, M j) ≃* M default 
goal: (MulEquiv.piUnique M).symm x i = uniqueElim x i

full_name: MulEquiv.piUnique
code: /-- A family indexed by a type with a unique element
is `MulEquiv` to the element at the single index. -/
@[to_additive (attr := simps!)
  "A family indexed by a type with a unique element
  is `AddEquiv` to the element at the single index."]
def piUnique {ι : Type*} (M : ι → Type*) [∀ j, Mul (M j)] [Unique ι] :
    (∀ j, M j) ≃* M default 
goal: ((j : ι) → M j) ≃* M default

full_name: AddEquiv.piUnique_symm_apply
code: /-- A family indexed by a type with a unique element
is `MulEquiv` to the element at the single index. -/
@[to_additive (attr := simps!)
  "A family indexed by a type with a unique element
  is `AddEquiv` to the element at the single index."]
def piUnique {ι : Type*} (M : ι → Type*) [∀ j, Mul (M j)] [Unique ι] :
    (∀ j, M j) ≃* M default 
goal: (AddEquiv.piUnique M).symm x i = uniqueElim x i

full_name: AddEquiv.piUnique_apply
code: /-- A family indexed by a type with a unique element
is `MulEquiv` to the element at the single index. -/
@[to_additive (attr := simps!)
  "A family indexed by a type with a unique element
  is `AddEquiv` to the element at the single index."]
def piUnique {ι : Type*} (M : ι → Type*) [∀ j, Mul (M j)] [Unique ι] :
    (∀ j, M j) ≃* M default 
goal: (AddEquiv.piUnique M) f = f default

full_name: MulEquiv.piUnique_apply
code: /-- A family indexed by a type with a unique element
is `MulEquiv` to the element at the single index. -/
@[to_additive (attr := simps!)
  "A family indexed by a type with a unique element
  is `AddEquiv` to the element at the single index."]
def piUnique {ι : Type*} (M : ι → Type*) [∀ j, Mul (M j)] [Unique ι] :
    (∀ j, M j) ≃* M default 
goal: (MulEquiv.piUnique M) f = f default

full_name: AddEquiv.piUnique
code: /-- A family indexed by a type with a unique element
is `MulEquiv` to the element at the single index. -/
@[to_additive (attr := simps!)
  "A family indexed by a type with a unique element
  is `AddEquiv` to the element at the single index."]
def piUnique {ι : Type*} (M : ι → Type*) [∀ j, Mul (M j)] [Unique ι] :
    (∀ j, M j) ≃* M default 
goal: ((j : ι) → M j) ≃+ M default

full_name: AddEquiv.map_neg
code: /-- A multiplicative equivalence of groups preserves inversion. -/
@[to_additive "An additive equivalence of additive groups preserves negation."]
protected theorem map_inv [Group G] [DivisionMonoid H] (h : G ≃* H) (x : G) :
    h x⁻¹ = (h x)⁻¹ 
goal: h (-x) = -h x

full_name: MulEquiv.map_inv
code: /-- A multiplicative equivalence of groups preserves inversion. -/
@[to_additive "An additive equivalence of additive groups preserves negation."]
protected theorem map_inv [Group G] [DivisionMonoid H] (h : G ≃* H) (x : G) :
    h x⁻¹ = (h x)⁻¹ 
goal: h x⁻¹ = (h x)⁻¹

full_name: AddEquiv.map_sub
code: /-- A multiplicative equivalence of groups preserves division. -/
@[to_additive "An additive equivalence of additive groups preserves subtractions."]
protected theorem map_div [Group G] [DivisionMonoid H] (h : G ≃* H) (x y : G) :
    h (x / y) = h x / h y 
goal: h (x - y) = h x - h y

full_name: MulEquiv.map_div
code: /-- A multiplicative equivalence of groups preserves division. -/
@[to_additive "An additive equivalence of additive groups preserves subtractions."]
protected theorem map_div [Group G] [DivisionMonoid H] (h : G ≃* H) (x y : G) :
    h (x / y) = h x / h y 
goal: h (x / y) = h x / h y

full_name: MulHom.toMulEquiv
code: /-- Given a pair of multiplicative homomorphisms `f`, `g` such that `g.comp f = id` and
`f.comp g = id`, returns a multiplicative equivalence with `toFun = f` and `invFun = g`. This
constructor is useful if the underlying type(s) have specialized `ext` lemmas for multiplicative
homomorphisms. -/
@[to_additive
  "Given a pair of additive homomorphisms `f`, `g` such that `g.comp f = id` and
  `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`. This
  constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive
  homomorphisms."]
def MulHom.toMulEquiv [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M) (h₁ : g.comp f = MulHom.id _)
    (h₂ : f.comp g = MulHom.id _) : M ≃* N 
goal: M ≃* N

full_name: AddHom.toAddEquiv
code: /-- Given a pair of multiplicative homomorphisms `f`, `g` such that `g.comp f = id` and
`f.comp g = id`, returns a multiplicative equivalence with `toFun = f` and `invFun = g`. This
constructor is useful if the underlying type(s) have specialized `ext` lemmas for multiplicative
homomorphisms. -/
@[to_additive
  "Given a pair of additive homomorphisms `f`, `g` such that `g.comp f = id` and
  `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`. This
  constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive
  homomorphisms."]
def MulHom.toMulEquiv [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M) (h₁ : g.comp f = MulHom.id _)
    (h₂ : f.comp g = MulHom.id _) : M ≃* N 
goal: M ≃+ N

full_name: AddHom.toAddEquiv_apply
code: @[to_additive (attr := simp)]
theorem MulHom.toMulEquiv_apply [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M)
    (h₁ : g.comp f = MulHom.id _) (h₂ : f.comp g = MulHom.id _) :
    ((MulHom.toMulEquiv f g h₁ h₂) : M → N) = f 
goal: ⇑(f.toAddEquiv g h₁ h₂) = ⇑f

full_name: MulHom.toMulEquiv_apply
code: @[to_additive (attr := simp)]
theorem MulHom.toMulEquiv_apply [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M)
    (h₁ : g.comp f = MulHom.id _) (h₂ : f.comp g = MulHom.id _) :
    ((MulHom.toMulEquiv f g h₁ h₂) : M → N) = f 
goal: ⇑(f.toMulEquiv g h₁ h₂) = ⇑f

full_name: AddHom.toAddEquiv_symm_apply
code: @[to_additive (attr := simp)]
theorem MulHom.toMulEquiv_symm_apply [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M)
    (h₁ : g.comp f = MulHom.id _) (h₂ : f.comp g = MulHom.id _) :
    (MulEquiv.symm (MulHom.toMulEquiv f g h₁ h₂) : N → M) = ↑g 
goal: ⇑(f.toAddEquiv g h₁ h₂).symm = ⇑g

full_name: MulHom.toMulEquiv_symm_apply
code: @[to_additive (attr := simp)]
theorem MulHom.toMulEquiv_symm_apply [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M)
    (h₁ : g.comp f = MulHom.id _) (h₂ : f.comp g = MulHom.id _) :
    (MulEquiv.symm (MulHom.toMulEquiv f g h₁ h₂) : N → M) = ↑g 
goal: ⇑(f.toMulEquiv g h₁ h₂).symm = ⇑g

full_name: MonoidHom.toMulEquiv
code: /-- Given a pair of monoid homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`,
returns a multiplicative equivalence with `toFun = f` and `invFun = g`.  This constructor is
useful if the underlying type(s) have specialized `ext` lemmas for monoid homomorphisms. -/
@[to_additive (attr := simps (config := .asFn))
  "Given a pair of additive monoid homomorphisms `f`, `g` such that `g.comp f = id`
  and `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`.  This
  constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive
  monoid homomorphisms."]
def MonoidHom.toMulEquiv [MulOneClass M] [MulOneClass N] (f : M →* N) (g : N →* M)
    (h₁ : g.comp f = MonoidHom.id _) (h₂ : f.comp g = MonoidHom.id _) : M ≃* N 
goal: M ≃* N

full_name: AddMonoidHom.toAddEquiv_symm_apply
code: /-- Given a pair of monoid homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`,
returns a multiplicative equivalence with `toFun = f` and `invFun = g`.  This constructor is
useful if the underlying type(s) have specialized `ext` lemmas for monoid homomorphisms. -/
@[to_additive (attr := simps (config := .asFn))
  "Given a pair of additive monoid homomorphisms `f`, `g` such that `g.comp f = id`
  and `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`.  This
  constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive
  monoid homomorphisms."]
def MonoidHom.toMulEquiv [MulOneClass M] [MulOneClass N] (f : M →* N) (g : N →* M)
    (h₁ : g.comp f = MonoidHom.id _) (h₂ : f.comp g = MonoidHom.id _) : M ≃* N 
goal: ⇑(f.toAddEquiv g h₁ h₂).symm = ⇑g

full_name: MonoidHom.toMulEquiv_apply
code: /-- Given a pair of monoid homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`,
returns a multiplicative equivalence with `toFun = f` and `invFun = g`.  This constructor is
useful if the underlying type(s) have specialized `ext` lemmas for monoid homomorphisms. -/
@[to_additive (attr := simps (config := .asFn))
  "Given a pair of additive monoid homomorphisms `f`, `g` such that `g.comp f = id`
  and `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`.  This
  constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive
  monoid homomorphisms."]
def MonoidHom.toMulEquiv [MulOneClass M] [MulOneClass N] (f : M →* N) (g : N →* M)
    (h₁ : g.comp f = MonoidHom.id _) (h₂ : f.comp g = MonoidHom.id _) : M ≃* N 
goal: ⇑(f.toMulEquiv g h₁ h₂) = ⇑f

full_name: AddMonoidHom.toAddEquiv
code: /-- Given a pair of monoid homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`,
returns a multiplicative equivalence with `toFun = f` and `invFun = g`.  This constructor is
useful if the underlying type(s) have specialized `ext` lemmas for monoid homomorphisms. -/
@[to_additive (attr := simps (config := .asFn))
  "Given a pair of additive monoid homomorphisms `f`, `g` such that `g.comp f = id`
  and `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`.  This
  constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive
  monoid homomorphisms."]
def MonoidHom.toMulEquiv [MulOneClass M] [MulOneClass N] (f : M →* N) (g : N →* M)
    (h₁ : g.comp f = MonoidHom.id _) (h₂ : f.comp g = MonoidHom.id _) : M ≃* N 
goal: M ≃+ N

full_name: AddMonoidHom.toAddEquiv_apply
code: /-- Given a pair of monoid homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`,
returns a multiplicative equivalence with `toFun = f` and `invFun = g`.  This constructor is
useful if the underlying type(s) have specialized `ext` lemmas for monoid homomorphisms. -/
@[to_additive (attr := simps (config := .asFn))
  "Given a pair of additive monoid homomorphisms `f`, `g` such that `g.comp f = id`
  and `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`.  This
  constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive
  monoid homomorphisms."]
def MonoidHom.toMulEquiv [MulOneClass M] [MulOneClass N] (f : M →* N) (g : N →* M)
    (h₁ : g.comp f = MonoidHom.id _) (h₂ : f.comp g = MonoidHom.id _) : M ≃* N 
goal: ⇑(f.toAddEquiv g h₁ h₂) = ⇑f

full_name: MonoidHom.toMulEquiv_symm_apply
code: /-- Given a pair of monoid homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`,
returns a multiplicative equivalence with `toFun = f` and `invFun = g`.  This constructor is
useful if the underlying type(s) have specialized `ext` lemmas for monoid homomorphisms. -/
@[to_additive (attr := simps (config := .asFn))
  "Given a pair of additive monoid homomorphisms `f`, `g` such that `g.comp f = id`
  and `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`.  This
  constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive
  monoid homomorphisms."]
def MonoidHom.toMulEquiv [MulOneClass M] [MulOneClass N] (f : M →* N) (g : N →* M)
    (h₁ : g.comp f = MonoidHom.id _) (h₂ : f.comp g = MonoidHom.id _) : M ≃* N 
goal: ⇑(f.toMulEquiv g h₁ h₂).symm = ⇑g

full_name: Equiv.inv
code: /-- Inversion on a `Group` or `GroupWithZero` is a permutation of the underlying type. -/
@[to_additive (attr := simps! (config := .asFn) apply)
    "Negation on an `AddGroup` is a permutation of the underlying type."]
protected def inv : Perm G 
goal: Equiv.Perm G

full_name: Equiv.neg
code: /-- Inversion on a `Group` or `GroupWithZero` is a permutation of the underlying type. -/
@[to_additive (attr := simps! (config := .asFn) apply)
    "Negation on an `AddGroup` is a permutation of the underlying type."]
protected def inv : Perm G 
goal: Equiv.Perm G

full_name: Equiv.inv_apply
code: /-- Inversion on a `Group` or `GroupWithZero` is a permutation of the underlying type. -/
@[to_additive (attr := simps! (config := .asFn) apply)
    "Negation on an `AddGroup` is a permutation of the underlying type."]
protected def inv : Perm G 
goal: ⇑(Equiv.inv G) = Inv.inv

full_name: Equiv.neg_apply
code: /-- Inversion on a `Group` or `GroupWithZero` is a permutation of the underlying type. -/
@[to_additive (attr := simps! (config := .asFn) apply)
    "Negation on an `AddGroup` is a permutation of the underlying type."]
protected def inv : Perm G 
goal: ⇑(Equiv.neg G) = Neg.neg

full_name: Equiv.inv_symm
code: @[to_additive (attr := simp)]
theorem inv_symm : (Equiv.inv G).symm = Equiv.inv G 
goal: Equiv.symm (Equiv.inv G) = Equiv.inv G

full_name: Equiv.neg_symm
code: @[to_additive (attr := simp)]
theorem inv_symm : (Equiv.inv G).symm = Equiv.inv G 
goal: Equiv.symm (Equiv.neg G) = Equiv.neg G