mathlib documentation

algebra.group.defs

Typeclasses for (semi)groups and monoids #

In this file we define typeclasses for algebraic structures with one binary operation. The classes are named (add_)?(comm_)?(semigroup|monoid|group), where add_ means that the class uses additive notation and comm_ means that the class assumes that the binary operation is commutative.

The file does not contain any lemmas except for

For basic lemmas about these classes see algebra.group.basic.

def left_mul {G : Type u} [has_mul G] :
G → G → G

left_mul g denotes left multiplication by g

Equations
def left_add {G : Type u} [has_add G] :
G → G → G

left_add g denotes left addition by g

def right_add {G : Type u} [has_add G] :
G → G → G

right_add g denotes right addition by g

def right_mul {G : Type u} [has_mul G] :
G → G → G

right_mul g denotes right multiplication by g

Equations
theorem semigroup.ext_iff {G : Type u} (x y : semigroup G) :
theorem semigroup.ext {G : Type u} (x y : semigroup G) (h : semigroup.mul = semigroup.mul) :
x = y
@[instance]
def semigroup.to_has_mul (G : Type u) [self : semigroup G] :
@[instance]
def add_semigroup.to_has_add (G : Type u) [self : add_semigroup G] :
theorem add_semigroup.ext {G : Type u} (x y : add_semigroup G) (h : add_semigroup.add = add_semigroup.add) :
x = y
theorem add_assoc {G : Type u} [add_semigroup G] (a b c : G) :
a + b + c = a + (b + c)
theorem mul_assoc {G : Type u} [semigroup G] (a b c : G) :
(a * b) * c = a * b * c
@[instance]
def comm_semigroup.to_semigroup (G : Type u) [self : comm_semigroup G] :
theorem comm_semigroup.ext {G : Type u} (x y : comm_semigroup G) (h : comm_semigroup.mul = comm_semigroup.mul) :
x = y
@[instance]
theorem add_comm {G : Type u} [add_comm_semigroup G] (a b : G) :
a + b = b + a
theorem mul_comm {G : Type u} [comm_semigroup G] (a b : G) :
a * b = b * a
@[instance]
@[ext, class]
structure left_cancel_semigroup (G : Type u) :
Type u
  • mul : G → G → G
  • mul_assoc : ∀ (a b c : G), (a * b) * c = a * b * c
  • mul_left_cancel : ∀ (a b c : G), a * b = a * cb = c

A left_cancel_semigroup is a semigroup such that a * b = a * c implies b = c.

Instances
theorem mul_left_cancel {G : Type u} [left_cancel_semigroup G] {a b c : G} :
a * b = a * cb = c
theorem add_left_cancel {G : Type u} [add_left_cancel_semigroup G] {a b c : G} :
a + b = a + cb = c
theorem add_left_cancel_iff {G : Type u} [add_left_cancel_semigroup G] {a b c : G} :
a + b = a + c b = c
theorem mul_left_cancel_iff {G : Type u} [left_cancel_semigroup G] {a b c : G} :
a * b = a * c b = c
@[simp]
theorem mul_right_inj {G : Type u} [left_cancel_semigroup G] (a : G) {b c : G} :
a * b = a * c b = c
@[simp]
theorem add_right_inj {G : Type u} [add_left_cancel_semigroup G] (a : G) {b c : G} :
a + b = a + c b = c
theorem mul_ne_mul_right {G : Type u} [left_cancel_semigroup G] (a : G) {b c : G} :
a * b a * c b c
theorem add_ne_add_right {G : Type u} [add_left_cancel_semigroup G] (a : G) {b c : G} :
a + b a + c b c
@[ext, class]
structure right_cancel_semigroup (G : Type u) :
Type u
  • mul : G → G → G
  • mul_assoc : ∀ (a b c : G), (a * b) * c = a * b * c
  • mul_right_cancel : ∀ (a b c : G), a * b = c * ba = c

A right_cancel_semigroup is a semigroup such that a * b = c * b implies a = c.

Instances
@[instance]
theorem mul_right_cancel {G : Type u} [right_cancel_semigroup G] {a b c : G} :
a * b = c * ba = c
theorem add_right_cancel {G : Type u} [add_right_cancel_semigroup G] {a b c : G} :
a + b = c + ba = c
theorem mul_right_cancel_iff {G : Type u} [right_cancel_semigroup G] {a b c : G} :
b * a = c * a b = c
theorem add_right_cancel_iff {G : Type u} [add_right_cancel_semigroup G] {a b c : G} :
b + a = c + a b = c
theorem add_left_injective {G : Type u} [add_right_cancel_semigroup G] (a : G) :
function.injective (λ (x : G), x + a)
theorem mul_left_injective {G : Type u} [right_cancel_semigroup G] (a : G) :
function.injective (λ (x : G), x * a)
@[simp]
theorem add_left_inj {G : Type u} [add_right_cancel_semigroup G] (a : G) {b c : G} :
b + a = c + a b = c
@[simp]
theorem mul_left_inj {G : Type u} [right_cancel_semigroup G] (a : G) {b c : G} :
b * a = c * a b = c
theorem mul_ne_mul_left {G : Type u} [right_cancel_semigroup G] (a : G) {b c : G} :
b * a c * a b c
theorem add_ne_add_left {G : Type u} [add_right_cancel_semigroup G] (a : G) {b c : G} :
b + a c + a b c
@[class]
structure mul_one_class (M : Type u) :
Type u
  • one : M
  • mul : M → M → M
  • one_mul : ∀ (a : M), 1 * a = a
  • mul_one : ∀ (a : M), a * 1 = a

Typeclass for expressing that a type M with multiplication and a one satisfies 1 * a = a and a * 1 = a for all a : M.

Instances
@[instance]
def mul_one_class.to_has_one (M : Type u) [self : mul_one_class M] :
@[instance]
def mul_one_class.to_has_mul (M : Type u) [self : mul_one_class M] :
@[instance]
def add_zero_class.to_has_add (M : Type u) [self : add_zero_class M] :
@[instance]
def add_zero_class.to_has_zero (M : Type u) [self : add_zero_class M] :
@[class]
structure add_zero_class (M : Type u) :
Type u
  • zero : M
  • add : M → M → M
  • zero_add : ∀ (a : M), 0 + a = a
  • add_zero : ∀ (a : M), a + 0 = a

Typeclass for expressing that a type M with addition and a zero satisfies 0 + a = a and a + 0 = a for all a : M.

Instances
@[ext]
theorem mul_one_class.ext {M : Type u} ⦃m₁ m₂ : mul_one_class M⦄ :
@[ext]
theorem add_zero_class.ext {M : Type u} ⦃m₁ m₂ : add_zero_class M⦄ :
@[simp]
theorem one_mul {M : Type u} [mul_one_class M] (a : M) :
1 * a = a
@[simp]
theorem zero_add {M : Type u} [add_zero_class M] (a : M) :
0 + a = a
@[simp]
theorem add_zero {M : Type u} [add_zero_class M] (a : M) :
a + 0 = a
@[simp]
theorem mul_one {M : Type u} [mul_one_class M] (a : M) :
a * 1 = a
@[instance]
@[instance]
@[instance]
def npow_rec {M : Type u} [has_one M] [has_mul M] :
M → M

The fundamental power operation in a monoid. npow_rec n a = a*a*...*a n times. Use instead a ^ n, which has better definitional behavior.

Equations
def nsmul_rec {M : Type u} [has_zero M] [has_add M] :
M → M

The fundamental scalar multiplication in an additive monoid. nsmul_rec n a = a+a+...+a n times. Use instead n • a, which has better definitional behavior.

Equations
meta def try_refl_tac  :

try_refl_tac solves goals of the form ∀ a b, f a b = g a b, if they hold by definition.

Design note on add_monoid and monoid #

An add_monoid has a natural -action, defined by n • a = a + ... + a, that we want to declare as an instance as it makes it possible to use the language of linear algebra. However, there are often other natural -actions. For instance, for any semiring R, the space of polynomials polynomial R has a natural R-action defined by multiplication on the coefficients. This means that polynomial would have two natural -actions, which are equal but not defeq. The same goes for linear maps, tensor products, and so on (and even for itself).

To solve this issue, we embed an -action in the definition of an add_monoid (which is by default equal to the naive action a + ... + a, but can be adjusted when needed), and declare a has_scalar ℕ α instance using this action. See Note [forgetful inheritance] for more explanations on this pattern.

For example, when we define polynomial R, then we declare the -action to be by multiplication on each coefficient (using the -action on R that comes from the fact that R is an add_monoid). In this way, the two natural has_scalar ℕ (polynomial ℕ) instances are defeq.

The tactic to_additive transfers definitions and results from multiplicative monoids to additive monoids. To work, it has to map fields to fields. This means that we should also add corresponding fields to the multiplicative structure monoid, which could solve defeq problems for powers if needed. These problems do not come up in practice, so most of the time we will not need to adjust the npow field when defining multiplicative objects.

Nice notation and a basic theory for the power function on monoids and the -action on additive monoids are built in the file algebra.group_power.basic. For now, we only register the most basic properties that we need right away.

In the definition, we use n.succ instead of n + 1 in the nsmul_succ' and npow_succ' fields to make sure that to_additive is not confused (otherwise, it would try to convert 1 : ℕ to 0 : ℕ).

@[instance]
def add_monoid.to_add_semigroup (M : Type u) [self : add_monoid M] :
@[instance]
def add_monoid.to_add_zero_class (M : Type u) [self : add_monoid M] :
@[class]
structure add_monoid (M : Type u) :
Type u
  • add : M → M → M
  • add_assoc : ∀ (a b c : M), a + b + c = a + (b + c)
  • zero : M
  • zero_add : ∀ (a : M), 0 + a = a
  • add_zero : ∀ (a : M), a + 0 = a
  • nsmul : M → M
  • nsmul_zero' : (∀ (x : M), nsmul 0 x = 0) . "try_refl_tac"
  • nsmul_succ' : (∀ (n : ) (x : M), nsmul n.succ x = x + nsmul n x) . "try_refl_tac"

An add_monoid is an add_semigroup with an element 0 such that 0 + a = a + 0 = a.

Instances
@[instance]
def monoid.to_mul_one_class (M : Type u) [self : monoid M] :
@[instance]
def monoid.to_semigroup (M : Type u) [self : monoid M] :
@[class]
structure monoid (M : Type u) :
Type u
  • mul : M → M → M
  • mul_assoc : ∀ (a b c : M), (a * b) * c = a * b * c
  • one : M
  • one_mul : ∀ (a : M), 1 * a = a
  • mul_one : ∀ (a : M), a * 1 = a
  • npow : M → M
  • npow_zero' : (∀ (x : M), npow 0 x = 1) . "try_refl_tac"
  • npow_succ' : (∀ (n : ) (x : M), npow n.succ x = x * npow n x) . "try_refl_tac"

A monoid is a semigroup with an element 1 such that 1 * a = a * 1 = a.

Instances
@[ext]
theorem monoid.ext {M : Type u_1} ⦃m₁ m₂ : monoid M⦄ (h_mul : monoid.mul = monoid.mul) :
m₁ = m₂
@[ext]
theorem add_monoid.ext {M : Type u_1} ⦃m₁ m₂ : add_monoid M⦄ (h_mul : add_monoid.add = add_monoid.add) :
m₁ = m₂
theorem left_inv_eq_right_inv {M : Type u} [monoid M] {a b c : M} (hba : b * a = 1) (hac : a * c = 1) :
b = c
theorem left_neg_eq_right_neg {M : Type u} [add_monoid M] {a b c : M} (hba : b + a = 0) (hac : a + c = 0) :
b = c
theorem npow_one {M : Type u} [monoid M] (x : M) :
npow 1 x = x
theorem nsmul_one' {M : Type u} [add_monoid M] (x : M) :
nsmul 1 x = x
theorem nsmul_add' {M : Type u} [add_monoid M] (m n : ) (x : M) :
nsmul (m + n) x = nsmul m x + nsmul n x
theorem npow_add {M : Type u} [monoid M] (m n : ) (x : M) :
npow (m + n) x = (npow m x) * npow n x
@[instance]
def add_comm_monoid.to_add_monoid (M : Type u) [self : add_comm_monoid M] :
@[class]
structure add_comm_monoid (M : Type u) :
Type u

An additive commutative monoid is an additive monoid with commutative (+).

Instances
@[instance]
def comm_monoid.to_comm_semigroup (M : Type u) [self : comm_monoid M] :
@[class]
structure comm_monoid (M : Type u) :
Type u
  • mul : M → M → M
  • mul_assoc : ∀ (a b c : M), (a * b) * c = a * b * c
  • one : M
  • one_mul : ∀ (a : M), 1 * a = a
  • mul_one : ∀ (a : M), a * 1 = a
  • npow : M → M
  • npow_zero' : (∀ (x : M), comm_monoid.npow 0 x = 1) . "try_refl_tac"
  • npow_succ' : (∀ (n : ) (x : M), comm_monoid.npow n.succ x = x * comm_monoid.npow n x) . "try_refl_tac"
  • mul_comm : ∀ (a b : M), a * b = b * a

A commutative monoid is a monoid with commutative (*).

Instances
@[instance]
def comm_monoid.to_monoid (M : Type u) [self : comm_monoid M] :
@[ext]
theorem comm_monoid.ext {M : Type u_1} ⦃m₁ m₂ : comm_monoid M⦄ (h_mul : comm_monoid.mul = comm_monoid.mul) :
m₁ = m₂
@[ext]
theorem add_comm_monoid.ext {M : Type u_1} ⦃m₁ m₂ : add_comm_monoid M⦄ (h_mul : add_comm_monoid.add = add_comm_monoid.add) :
m₁ = m₂
@[instance]
@[class]
structure add_left_cancel_monoid (M : Type u) :
Type u

An additive monoid in which addition is left-cancellative. Main examples are and groups. This is the right typeclass for many sum lemmas, as having a zero is useful to define the sum over the empty set, so add_left_cancel_semigroup is not enough.

Instances
@[class]
structure left_cancel_monoid (M : Type u) :
Type u

A monoid in which multiplication is left-cancellative.

Instances
@[instance]
def left_cancel_monoid.to_monoid (M : Type u) [self : left_cancel_monoid M] :
@[ext]
theorem left_cancel_monoid.ext {M : Type u_1} ⦃m₁ m₂ : left_cancel_monoid M⦄ (h_mul : left_cancel_monoid.mul = left_cancel_monoid.mul) :
m₁ = m₂
@[ext]
theorem add_left_cancel_monoid.ext {M : Type u_1} ⦃m₁ m₂ : add_left_cancel_monoid M⦄ (h_mul : add_left_cancel_monoid.add = add_left_cancel_monoid.add) :
m₁ = m₂
@[class]
structure add_right_cancel_monoid (M : Type u) :
Type u

An additive monoid in which addition is right-cancellative. Main examples are and groups. This is the right typeclass for many sum lemmas, as having a zero is useful to define the sum over the empty set, so add_right_cancel_semigroup is not enough.

Instances
@[instance]
def right_cancel_monoid.to_monoid (M : Type u) [self : right_cancel_monoid M] :
@[class]
structure right_cancel_monoid (M : Type u) :
Type u

A monoid in which multiplication is right-cancellative.

Instances
@[ext]
theorem add_right_cancel_monoid.ext {M : Type u_1} ⦃m₁ m₂ : add_right_cancel_monoid M⦄ (h_mul : add_right_cancel_monoid.add = add_right_cancel_monoid.add) :
m₁ = m₂
@[ext]
theorem right_cancel_monoid.ext {M : Type u_1} ⦃m₁ m₂ : right_cancel_monoid M⦄ (h_mul : right_cancel_monoid.mul = right_cancel_monoid.mul) :
m₁ = m₂
@[class]
structure add_cancel_monoid (M : Type u) :
Type u

An additive monoid in which addition is cancellative on both sides. Main examples are and groups. This is the right typeclass for many sum lemmas, as having a zero is useful to define the sum over the empty set, so add_right_cancel_semigroup is not enough.

Instances
@[instance]
@[class]
structure cancel_monoid (M : Type u) :
Type u
  • mul : M → M → M
  • mul_assoc : ∀ (a b c : M), (a * b) * c = a * b * c
  • mul_left_cancel : ∀ (a b c : M), a * b = a * cb = c
  • one : M
  • one_mul : ∀ (a : M), 1 * a = a
  • mul_one : ∀ (a : M), a * 1 = a
  • npow : M → M
  • npow_zero' : (∀ (x : M), cancel_monoid.npow 0 x = 1) . "try_refl_tac"
  • npow_succ' : (∀ (n : ) (x : M), cancel_monoid.npow n.succ x = x * cancel_monoid.npow n x) . "try_refl_tac"
  • mul_right_cancel : ∀ (a b c : M), a * b = c * ba = c

A monoid in which multiplication is cancellative.

Instances
@[instance]
@[ext]
theorem add_cancel_monoid.ext {M : Type u_1} ⦃m₁ m₂ : add_cancel_monoid M⦄ (h_mul : add_cancel_monoid.add = add_cancel_monoid.add) :
m₁ = m₂
@[ext]
theorem cancel_monoid.ext {M : Type u_1} ⦃m₁ m₂ : cancel_monoid M⦄ (h_mul : cancel_monoid.mul = cancel_monoid.mul) :
m₁ = m₂
@[class]
structure add_cancel_comm_monoid (M : Type u) :
Type u

Commutative version of add_cancel_monoid.

Instances
@[instance]
@[class]
structure cancel_comm_monoid (M : Type u) :
Type u

Commutative version of cancel_monoid.

Instances
@[ext]
theorem add_cancel_comm_monoid.ext {M : Type u_1} ⦃m₁ m₂ : add_cancel_comm_monoid M⦄ (h_mul : add_cancel_comm_monoid.add = add_cancel_comm_monoid.add) :
m₁ = m₂
@[ext]
theorem cancel_comm_monoid.ext {M : Type u_1} ⦃m₁ m₂ : cancel_comm_monoid M⦄ (h_mul : cancel_comm_monoid.mul = cancel_comm_monoid.mul) :
m₁ = m₂
def gpow_rec {M : Type u_1} [has_one M] [has_mul M] [has_inv M] :
M → M

The fundamental power operation in a group. gpow_rec n a = a*a*...*a n times, for integer n. Use instead a ^ n, which has better definitional behavior.

Equations
def gsmul_rec {M : Type u_1} [has_zero M] [has_add M] [has_neg M] :
M → M

The fundamental scalar multiplication in an additive group. gsmul_rec n a = a+a+...+a n times, for integer n. Use instead n • a, which has better definitional behavior.

Equations
@[instance]
def div_inv_monoid.to_monoid (G : Type u) [self : div_inv_monoid G] :
@[instance]
def div_inv_monoid.to_has_div (G : Type u) [self : div_inv_monoid G] :
@[class]
structure div_inv_monoid (G : Type u) :
Type u

A div_inv_monoid is a monoid with operations / and ⁻¹ satisfying div_eq_mul_inv : ∀ a b, a / b = a * b⁻¹.

This is the immediate common ancestor of group and group_with_zero, in order to deduplicate the name div_eq_mul_inv. The default for div is such that a / b = a * b⁻¹ holds by definition.

Adding div as a field rather than defining a / b := a * b⁻¹ allows us to avoid certain classes of unification failures, for example: Let foo X be a type with a ∀ X, has_div (foo X) instance but no ∀ X, has_inv (foo X), e.g. when foo X is a euclidean_domain. Suppose we also have an instance ∀ X [cromulent X], group_with_zero (foo X). Then the (/) coming from group_with_zero_has_div cannot be definitionally equal to the (/) coming from foo.has_div.

In the same way, adding a gpow field makes it possible to avoid definitional failures in diamonds. See the definition of monoid and Note [forgetful inheritance] for more explanations on this.

Instances
@[instance]
def div_inv_monoid.to_has_inv (G : Type u) [self : div_inv_monoid G] :
@[instance]
def sub_neg_monoid.to_has_sub (G : Type u) [self : sub_neg_monoid G] :
@[instance]
def sub_neg_monoid.to_add_monoid (G : Type u) [self : sub_neg_monoid G] :
@[class]
structure sub_neg_monoid (G : Type u) :
Type u

A sub_neg_monoid is an add_monoid with unary - and binary - operations satisfying sub_eq_add_neg : ∀ a b, a - b = a + -b.

The default for sub is such that a - b = a + -b holds by definition.

Adding sub as a field rather than defining a - b := a + -b allows us to avoid certain classes of unification failures, for example: Let foo X be a type with a ∀ X, has_sub (foo X) instance but no ∀ X, has_neg (foo X). Suppose we also have an instance ∀ X [cromulent X], add_group (foo X). Then the (-) coming from add_group.has_sub cannot be definitionally equal to the (-) coming from foo.has_sub.

In the same way, adding a gsmul field makes it possible to avoid definitional failures in diamonds. See the definition of add_monoid and Note [forgetful inheritance] for more explanations on this.

Instances
@[instance]
def sub_neg_monoid.to_has_neg (G : Type u) [self : sub_neg_monoid G] :
@[ext]
theorem div_inv_monoid.ext {M : Type u_1} ⦃m₁ m₂ : div_inv_monoid M⦄ (h_mul : div_inv_monoid.mul = div_inv_monoid.mul) (h_inv : div_inv_monoid.inv = div_inv_monoid.inv) :
m₁ = m₂
@[ext]
theorem sub_neg_monoid.ext {M : Type u_1} ⦃m₁ m₂ : sub_neg_monoid M⦄ (h_mul : sub_neg_monoid.add = sub_neg_monoid.add) (h_inv : sub_neg_monoid.neg = sub_neg_monoid.neg) :
m₁ = m₂
theorem div_eq_mul_inv {G : Type u} [div_inv_monoid G] (a b : G) :
a / b = a * b⁻¹
theorem sub_eq_add_neg {G : Type u} [sub_neg_monoid G] (a b : G) :
a - b = a + -b
@[class]
structure group (G : Type u) :
Type u

A group is a monoid with an operation ⁻¹ satisfying a⁻¹ * a = 1.

There is also a division operation / such that a / b = a * b⁻¹, with a default so that a / b = a * b⁻¹ holds by definition.

Instances
@[instance]
def group.to_div_inv_monoid (G : Type u) [self : group G] :
@[class]
structure add_group (A : Type u) :
Type u

An add_group is an add_monoid with a unary - satisfying -a + a = 0.

There is also a binary operation - such that a - b = a + -b, with a default so that a - b = a + -b holds by definition.

Instances
@[instance]
def add_group.to_sub_neg_monoid (A : Type u) [self : add_group A] :
def add_group.to_add_monoid (G : Type u) [add_group G] :

Abbreviation for @sub_neg_monoid.to_add_monoid _ (@add_group.to_sub_neg_monoid _ _).

Useful because it corresponds to the fact that AddGroup is a subcategory of AddMon. Not an instance since it duplicates @sub_neg_monoid.to_add_monoid _ (@add_group.to_sub_neg_monoid _ _).

def group.to_monoid (G : Type u) [group G] :

Abbreviation for @div_inv_monoid.to_monoid _ (@group.to_div_inv_monoid _ _).

Useful because it corresponds to the fact that Grp is a subcategory of Mon. Not an instance since it duplicates @div_inv_monoid.to_monoid _ (@group.to_div_inv_monoid _ _). See note [reducible non-instances].

Equations
@[simp]
theorem add_left_neg {G : Type u} [add_group G] (a : G) :
-a + a = 0
@[simp]
theorem mul_left_inv {G : Type u} [group G] (a : G) :
a⁻¹ * a = 1
theorem neg_add_self {G : Type u} [add_group G] (a : G) :
-a + a = 0
theorem inv_mul_self {G : Type u} [group G] (a : G) :
a⁻¹ * a = 1
@[simp]
theorem inv_mul_cancel_left {G : Type u} [group G] (a b : G) :
a⁻¹ * a * b = b
@[simp]
theorem neg_add_cancel_left {G : Type u} [add_group G] (a b : G) :
-a + (a + b) = b
@[simp]
theorem inv_eq_of_mul_eq_one {G : Type u} [group G] {a b : G} (h : a * b = 1) :
a⁻¹ = b
@[simp]
theorem neg_eq_of_add_eq_zero {G : Type u} [add_group G] {a b : G} (h : a + b = 0) :
-a = b
@[simp]
theorem inv_inv {G : Type u} [group G] (a : G) :
@[simp]
theorem neg_neg {G : Type u} [add_group G] (a : G) :
--a = a
@[simp]
theorem mul_right_inv {G : Type u} [group G] (a : G) :
a * a⁻¹ = 1
@[simp]
theorem add_right_neg {G : Type u} [add_group G] (a : G) :
a + -a = 0
theorem add_neg_self {G : Type u} [add_group G] (a : G) :
a + -a = 0
theorem mul_inv_self {G : Type u} [group G] (a : G) :
a * a⁻¹ = 1
@[simp]
theorem add_neg_cancel_right {G : Type u} [add_group G] (a b : G) :
a + b + -b = a
@[simp]
theorem mul_inv_cancel_right {G : Type u} [group G] (a b : G) :
(a * b) * b⁻¹ = a
@[instance]
def group.to_cancel_monoid {G : Type u} [group G] :
Equations
@[instance]
@[ext]
theorem group.ext {G : Type u_1} ⦃g₁ g₂ : group G⦄ (h_mul : group.mul = group.mul) :
g₁ = g₂
@[ext]
theorem add_group.ext {G : Type u_1} ⦃g₁ g₂ : add_group G⦄ (h_mul : add_group.add = add_group.add) :
g₁ = g₂
@[instance]
def comm_group.to_group (G : Type u) [self : comm_group G] :
@[class]
structure comm_group (G : Type u) :
Type u

A commutative group is a group with commutative (*).

Instances
@[instance]
def comm_group.to_comm_monoid (G : Type u) [self : comm_group G] :
@[class]
structure add_comm_group (G : Type u) :
Type u

An additive commutative group is an additive group with commutative (+).

Instances
@[instance]
@[instance]
def add_comm_group.to_add_group (G : Type u) [self : add_comm_group G] :
@[ext]
theorem comm_group.ext {G : Type u_1} ⦃g₁ g₂ : comm_group G⦄ (h_mul : comm_group.mul = comm_group.mul) :
g₁ = g₂
@[ext]
theorem add_comm_group.ext {G : Type u_1} ⦃g₁ g₂ : add_comm_group G⦄ (h_mul : add_comm_group.add = add_comm_group.add) :
g₁ = g₂
@[instance]
Equations