Interactive Theorem Proving in Lean

Lean logo QR code link to these slides

Lecture 4: Algebraic structures.

GRACE Spring School, Clervaux (Luxembourg). June 1-5, 2026.
Florent Schaffhauser, Heidelberg University.

Lecture 4: Algebraic structures

Recap from Lecture 3

  • Besides simply-typed functions, we can define type formers, polymorphic functions and type families.

  • To a type family F : X → Type, we can associate:

    • The type of dependent pairs (x : X) × F x, which is a -type.
    • The type of dependent functions (x : X) → F x, which is a -type.
  • Given a predicate P : X → Prop, the proposition ∃ x : X, P x is the proposition whose proofs are constructed using dependent pairs (x : X) ×' P x. And a proof of the proposition ∀ x : X, P x is a dependent function, of type (x : X) → P x.

  • In this lecture, we will see how to formalize basic algebraic structures (monoids and groups).

Lecture 4: Algebraic structures

Advanced tactics

If you prefer to learn more about tactics, here is a practice file on advanced tactics.

Practice File QR Code

Lecture 4: Algebraic structures

Algebraic structures

  • So far, we have used dependent type theory as a syntax in which to express mathematical statements such as the following.

    theorem FLT {n : Nat} (x y z : Int) : 
      (n > 2) → x ^ n + y ^ n = z ^ n → x * y * z = 0 := sorry
    
  • But we can also use it to represent mathematical objects such as groups, rings, or topological spaces.

  • To do this in a programming language such as Lean, it is useful to first have a sense of what a record is.

Lecture 4: Algebraic structures

Plan for Lecture 4

  1. Record types
  2. Monoids and groups
  3. Extended structures and coercions
Lecture 4: Algebraic structures
Record types

Record types

  • As a first approximation, you can think of a record type as an inductive type with only one constructor. The terms of a record type represent what we think of as tuples.

  • In Lean, record types are introduced via the keyword structure.

  • The product of two types, for instance, can be defined as a structure.

    structure Prod (X : Type) (Y : Type) where
      mk :: (x : X) (y : Y)
    
  • The declaration as an inductive type used quite similar syntax:

    inductive Prod (X : Type) (Y : Type) where
    | mk (x : X) (y : Y) : Prod X Y
    
Lecture 4: Algebraic structures
Record types

Fields of a structure

  • While valid, the previous syntax for declaring Prod X Y as a record is not very enlightening. Recall:

    structure Prod (X : Type) (Y : Type) : Type where
      mk :: (x : X) (y : Y)
    
  • Try instead:

    structure Prod (X : Type) (Y : Type) : Type where
      mk ::      -- indicating the constructor's name is optional (try it!)
        fst : X 
        snd : Y
    
  • Here, Prod is presented as a structure with two fields, named fst and snd.

Lecture 4: Algebraic structures
Record types

Projections

  • Record types come equipped with projections to their fields:

    #check Prod.fst  -- Prod.fst : {X Y : Type} → Prod X Y → X
    #check Prod.snd  -- Prod.snd : {X Y : Type} → Prod X Y → Y
    
  • The name of the field should reflect that: Prod.fst is much more expressive than Prod.x as a name for the first projection.

  • A convenient feature of these projections is that you can use dot notation.

    #check (2, -1)      -- (2, -1) : Nat × Int
    #check (2, -1).fst  -- (2, -1).fst : Nat
    #eval  (2, -1).fst  -- 2
    
Lecture 4: Algebraic structures
Monoids and groups
  1. Record types
  2. Monoids and groups
  3. Extended structures and coercions
Lecture 4: Algebraic structures
Monoids and groups

Monoids

  • In mathematics, a monoid is a triple where:

    • is a set (called the carrier or the underlying set of the monoid ).
    • is an associative operation on , meaning that

    • is a neutral element for the operation , meaning that

  • Since a monoid is some kind of tuple, it is natural to translate this directly into a record type in Lean. We just have to unpack the information about and .

Lecture 4: Algebraic structures
Monoids and groups

The type of monoids

  • The type of monoids can be introduced as follows in Lean.

    structure Monoid where
      carrier : Type
      op      : carrier → carrier → carrier 
      assoc   :  x y z : carrier, op (op x y) z = op  x (op y z)
      elt     : carrier
      neutral :  x : carrier, (op elt x = x) ∧ (op x elt = x)
    
  • Note how the field op depends on the field carrier and how the fields assoc and neutral depend on the fields carrier, op and elt.

  • Also note that the proof of the associativity property is part of the definition 🤯. Same for the proof of the fact that elt is a neutral element.

Lecture 4: Algebraic structures
Monoids and groups

Construction of monoids

  • Concretely, how do we construct a monoid? We must supply a term for each field of the Monoid structure.

    def NatAddZero : Monoid where
      carrier := Nat
      op      := Nat.add
      assoc   := Nat.add_assoc
      elt     := Nat.zero
      neutral := fun (n : Nat) ↦ ⟨Nat.zero_add n, Nat.add_zero n⟩
    
  • Note the use of the where keyword, after which we can specify each field separately. The constructor Monoid.mk does not appear anywhere.

  • This works because Nat.add, Nat.add_assoc, etc are already contained in Lean's standard library. The term you need can be defined there directly (see neutral above).

Lecture 4: Algebraic structures
Monoids and groups

Using a tactic proof to construct a monoid

  • You can also use a tactic program to write terms that go into the various fields.

    def NatAddZero : Monoid where
      carrier := by exact Nat
        ... (omitted)
      neutral := by
        intro n
        constructor
        exact Nat.zero_add n
        exact Nat.add_zero n
    
  • Or, without the where keyword (try it!):

    def NatAddZero : Monoid := by constructor; exact Nat; ... (omitted)
    
Lecture 4: Algebraic structures
Monoids and groups

Beware of existential quantifiers in the fields of a structure

  • One could also think of declaring the type of monoids as follows.

    structure Monoid where
      carrier : Type
      op      : carrier → carrier → carrier 
      assoc   :  x y z : carrier, op (op x y) z = op  x (op y z)
      neutral :  elt : carrier,  x : carrier, (op elt x = x) ∧ (op x elt = x)
    
  • The issue with this is that it is then unclear how to refer to the neutral element of a monoid, or if it is even possible to do so. In the previous construction, we had for instance NatAddZero.elt = Nat.zero (and that data can be extracted from the def).

  • This is problematic if we want to write the definition of a group: to add something like ∀ x : carrier, ∃ y : carrier, (op y x = elt) ∧ (op x y = elt), we need a term elt to refer to.

Lecture 4: Algebraic structures
Monoids and groups

Groups

  • There is a theoretical way out of the issues above (using a definite description operator), but in practice, we define the type of groups as follows, adding extra data (namely, the inverse map). Additional data and properties appear as additional fields in the structure.

    structure Group extends Monoid where
      inv_map  : carrier → carrier
      inv_ppty :  x : carrier, (op (inv_map x) x = elt) ∧ (op x (inv_map x) = elt)
    
  • There is no need to repeat the fields carrier, op, etc. They are part of the new structure and can be used when adding new fields. This also creates a projection map from Group to Monoid, which "forgets" the additional fields.

    #check @Group.toMonoid  -- Group.toMonoid : Group → Monoid
    
Lecture 4: Algebraic structures
Monoids and groups

Commutative groups

  • Notet that we can also extend the Monoid structure to CommMonoid, by adding a comutativity property.

    structure CommMonoid extends Monoid where
      comm :  x y : carrier, op x y = op y x
    
  • Then we can define commutative groups by extending the previous two structures, without adding any new field.

    structure CommGroup extends Group, CommMonoid
    

    This will not work if the two structures have a field with the same name,

Lecture 4: Algebraic structures
Monoids and groups

Exercises

  1. A basic exercise is to define the projection Group.toMonoid by hand.
  2. A more involved exercise is to state and prove a theorem saying that, if μ : Op X is an operation that admits a neutral element, then such an element is unique.
  3. A yet harder exercise is to construct a group whose carrier is the set of integers . For this, you will to use the standard library and search for basic results such as the associativity property of addition on Int, the fact that 0 : ℤ is left and right neutral, or the existence of an inverse (the exact? or simp? tactics may be of assistance).
Lecture 4: Algebraic structures
Monoids and groups

Property versus data

  • In general, it is good practice to separate property from data. This is linked to questions such as: is the type of groups (equivalent to) a subtype of the type of monoids?
  • The answer should be yes. However, because of the added data (namely, the inverse map), it is not clear that groups form a subtype of the type of monoids.
  • Can we show that two groups ⟨M, inv_map, inv_ppty⟩ and ⟨M', inv_map', inv_ppty'⟩ are equal if and only if M = M' as monoids? And what does this mean?
  • The issue is to show that inv_map = inv_map', a condition that only makes sense if M and M' have been identified, but then it reduces to the uniqueness of the inverse of an invertible element.
Lecture 4: Algebraic structures
Extended structures and coercions
  1. Record types
  2. Monoids and groups
  3. Extended structures and coercions
Lecture 4: Algebraic structures
Extended structures and coercions

Extended structures and coercions

  • Given a function f : Monoid → T and a term G : Group, we might want the expression f G to automatically type-check (without having to write f G.toMonoid). This can be achieved by implementing a coercion.

  • The automatization is taken care of via a mechanism called type-class inference. By specifying a function coe : Group → Monoid, our expression f G will automatically be interpreted as f (coe G). Here, coe is a function Group → Monoid.

    instance : Coe Group Monoid where
      coe := Group.toMonoid
    
  • The same kind of consideration arises if we extend the Monoid structure to a structure CommMonoid, with an additional field comm : ∀ x y : X, μ x y = μ y x.

Lecture 4: Algebraic structures
Extended structures and coercions

Coercion graph

Sometimes there is more than one possible coercion, which may cause conflicts known as diamonds if they are not compatible. In the present case, there is no issue, the diagram commutes!

Coercion graph for commutative groups

Lecture 4: Algebraic structures
Extended structures and coercions

Coercion to Type

  • Note that a term M : Monoid is not a type (it is a term of type Monoid). In particular, it does not make sense to write t : M. What would make sense, though, is t : M.carrier, because M.carrier is a type.

  • So when we say 'Let M be a monoid and let t be an element of M', what we mean is 'Let M be a monoid and let t be an element of M.carrier'. It would be nice, though, to be able to have t : M be parsed automatically as t : M.carrier.

  • The following coercion implements exactly that:

    instanceinstance instCoeSortMonoid : CoeSort Monoid Type where
      coe := fun (M : Monoid) ↦ M.carrier
    

    Here, coe is a function Monoid → Type.

Lecture 4: Algebraic structures
Extended structures and coercions

Wrap-up

  • It is useful to learn to distinguish property from data, in order to identify which -types are subtypes.
  • In practice, it is convenient to implement algebraic structures such as groups and rings as record types (structures, in Lean). This automatically gives us access to the various fields of the structure (meaning, the arguments of the constructor) via the appropriate projections.
  • Given a structure α and a structure β extending α, we can use the projection β.toα : β → α as a coercion from β to α. Thanks to a type-class inference mechanism, functions defined on α then become automatically applicable on terms of type β. Similarly, if a structure has a field carrier (or similar) that is a type, we can use the projection α.carrier : α → Type
Lecture 4: Algebraic structures
Extended structures and coercions

Practice time

Here is the practice file on advanced tactics again, as well as a practice file on algebraic structures. I am happy to answer any questions you may have 😊 .

Advanced tactics AlgebraicS tructures

Thank you for your attention!

Lecture 4: Algebraic structures

`comm : op.isCommutative`, where the predicate `Op.isCommutative` is defined by `∀ x y : X, μ x y = μ y x`.