Skip to content

Classical.Structures.Magma

Magmas β€” the empty-theory base case

This is the Classical.Structures.Magma module of the Agda Universal Algebra Library.

A magma is a set equipped with a single binary operation, with no further axioms imposed. Mathematically a magma is just an inhabitant of the type Algebra Sig-Magma Ξ± ρ: an Sig-Magma-algebra in the sense of universal algebra, with no theory to satisfy. This is the degenerate case of the general classical-structure encoding X Ξ± ρ = Ξ£[ 𝑨 ∈ Algebra 𝑆ₓ Ξ± ρ ] 𝑨 ⊨ Th-X; the Ξ£-wrapping vanishes when Th-X is empty (per ADR-002 v2 Β§5) and the representation collapses to a type alias.

This is also the first concrete classical structure to land in Milestone 3 (of the agda-algebras 3.0 upgrade) and, as such, this module's prose is normative for the signature-mechanics conventions every subsequent structure consumes.

Specifically: hyphen-separated <symbol>-Op constructor naming (in the corresponding Signatures/X file), ar-<Structure> arity-function naming, Sig-<Structure> signature-value naming, ASCII ^ for operation-symbol interpretation, a named <Structure>-Op module housing the curried user-facing accessors so that downstream code can open <Structure>-Op 𝑿 once and use the binary operation in infix form a βˆ™ b (mirroring the open Magma M-and-then-a βˆ™ b idiom of Algebra.Bundles), the curried-accessor body _βˆ™_ = Curryβ‚‚ (βˆ™-Op ^ _), and the opsTo<family> constructor pattern.

Semigroup, Monoid, Group, Lattice, and Ring all follow this template. (Deviations require an ADR.)

{-# OPTIONS --cubical-compatible --exact-split --safe #-}

module Classical.Structures.Magma where

-- Imports from Agda and the Agda Standard Library ----------------------------
open import Agda.Primitive                          using () renaming ( Set to Type )
open import Data.Fin.Patterns                       using ( 0F ; 1F )
open import Data.Product                            using ( _,_ ; proj₁ ; projβ‚‚ )
open import Function                                using ( Func )
open import Level                                   using ( Level ; _βŠ”_ ; suc )
open import Relation.Binary                         using ( Setoid )
import Relation.Binary.PropositionalEquality as ≑

open Func renaming ( to to _⟨$⟩_ )

-- Imports from the Agda Universal Algebra Library ----------------------------
open import Classical.Operations                    using ( Curryβ‚‚ ; pair )
open import Classical.Signatures.Magma              using ( βˆ™-Op ; Sig-Magma )
open import Classical.Structures.Interpret          using ( interp-cong )
open import Setoid.Algebras.Basic {𝑆 = Sig-Magma}   using ( Algebra ; _^_ ; 𝔻[_] ; π•Œ[_] )
open import Setoid.Homomorphisms.Basic              using ( hom ; IsHom )
open import Setoid.Signatures                       using ( ⟨_⟩ )

private variable α ρ : Level

The type of magmas

Magma Ξ± ρ is the type of Sig-Magma-algebras whose carrier sits at level Ξ± and whose underlying setoid equivalence sits at level ρ. Empty theory means no Ξ£-wrapping; the alias makes use sites read Magma Ξ± ρ rather than Algebra {𝑆 = Sig-Magma} Ξ± ρ.

Magma : (Ξ± ρ : Level) β†’ Type (suc Ξ± βŠ” suc ρ)
Magma α ρ = Algebra α ρ

(If it's not obvious why Algebra Ξ± ρ yields a magma here, note that the Setoid.Algebras.Basic module is imported above with the signature parameter set to 𝑆 = Sig-Magma.)

The Magma-Op module: named accessors for a fixed magma

Domain, Carrier, and _βˆ™_ are exposed inside a named parametric module Magma-Op. Users open Magma-Op 𝑴 at a use site to bring all three into scope; the binary operation is then expressed using infix notation a βˆ™ b, matching the experience of using open Magma M with the standard library's Algebra.Bundles.Magma module.

The name Magma-Op follows the hyphen-separated long-form convention established by Sig-Magma, ar-Magma, and βˆ™-Op. It is normative: every subsequent classical structure ships an analogously named module (Semigroup-Op, Monoid-Op, Group-Op, Lattice-Op, Ring-Op). Each later module additively re-exports the underlying weaker structure's operations through the forgetful projection; Group-Op exposes _βˆ™_, Ξ΅, and _⁻¹; Ring-Op exposes _+_, 0, -_, _Β·_, and 1. The "open the operations module once, use infix thereafter" idiom is uniform across the hierarchy.

The function _βˆ™_ interprets the syntactic operation symbol βˆ™-Op in the algebra 𝑴 and then curries the resulting (Fin 2 β†’ π•Œ[ 𝑴 ]) β†’ π•Œ[ 𝑴 ] into the user-facing π•Œ[ 𝑴 ] β†’ π•Œ[ 𝑴 ] β†’ π•Œ[ 𝑴 ]. The arity-tuple-vs-curried bridging is delegated to Curryβ‚‚ from Classical.Operations; the per-structure file never constructs pair-style argument tuples inline. This is what ADR-002 Β§1 requires: the Fin n Ξ·-bridge is contained inside one module library-wide.

When two magmas appear in the same expression β€” for example, both sides of a round-trip lemma in Classical.Bundles.Magma β€” the standard Agda idiom is

open Magma-Op 𝑴
open Magma-Op 𝑡 renaming (_βˆ™_ to _βˆ™'_)
module Magma-Op {Ξ± ρ : Level} (𝑴 : Magma Ξ± ρ) where
  infixl 7 _βˆ™_
  _βˆ™_ : π•Œ[ 𝑴 ] β†’ π•Œ[ 𝑴 ] β†’ π•Œ[ 𝑴 ]
  _βˆ™_ = Curryβ‚‚ (βˆ™-Op ^ 𝑴)

From a bare type and a binary operation

The single most common use case for downstream consumers is constructing a magma from a bare type A : Type Ξ± and a binary operation _Β·_ : A β†’ A β†’ A. The opsToMagma function performs the construction. The underlying setoid is the propositional-equality setoid ≑.setoid A, and the interpretation of βˆ™-Op uncurries _Β·_ back into the tuple-indexed form the algebra demands.

For structures with non-empty theory, the analogous constructor takes one additional argument per equation in the theory β€” eqsToSemigroup takes an associativity proof, eqsToMonoid takes associativity plus the two identity laws, and so on. Magma's empty theory means opsToMagma takes no equation arguments. This is the empty-theory edge case of the opsTo<family> constructor pattern.

opsToMagma : {A : Type Ξ±} (_Β·_ : A β†’ A β†’ A) β†’ Magma Ξ± Ξ±
opsToMagma {A = A} _Β·_ = record { Domain = ≑.setoid A ; Interp = interp }
  where
  interp : Func (⟨ Sig-Magma ⟩ _) _
  interp ⟨$⟩ (βˆ™-Op , args) = args 0F Β· args 1F
  cong interp {βˆ™-Op , _} {.βˆ™-Op , _} (≑.refl , args≑) = ≑.congβ‚‚ _Β·_ (args≑ 0F) (args≑ 1F)

A note on morphisms

A magma morphism is, by ADR-002 Β§5, definitionally a homomorphism of the underlying Sig-Magma-algebras. No per-structure morphism record is introduced; we inherit Setoid.Homomorphisms wholesale, instantiated at 𝑆 = Sig-Magma. This is uniformly the policy across the classical hierarchy: each structure inherits homomorphisms, isomorphisms, and substructure machinery from Setoid/ instantiated at its own signature. Per-structure morphism invariants β€” for example, "monoid homomorphisms preserve the identity element" β€” are theorems about the inherited homomorphism, not new record fields.

The first such invariant is the inherited homomorphism's compatibility with βˆ™-Op restated in curried form: h (x βˆ™ y) β‰ˆ h x βˆ™ h y. The compatible field of IsHom states this against argument tuples (h ((βˆ™-Op ^ 𝑨) a) β‰ˆ (βˆ™-Op ^ 𝑩) (h ∘ a)); hom-preserves-βˆ™ instantiates the tuple at pair x y and pays the Fin 2 Ξ·-bridge once, via interp-cong, so downstream consumers (e.g. the free-expansion functor) get the curried law as a one-liner.

module _ {Ξ± Ξ² ρᡃ ρᡇ : Level} {𝑨 : Magma Ξ± ρᡃ} {𝑩 : Magma Ξ² ρᡇ} where
  open Magma-Op 𝑨 using ( _βˆ™_ )
  open Magma-Op 𝑩 using () renaming ( _βˆ™_ to _βˆ™α΅‡_ )
  open Setoid 𝔻[ 𝑩 ] using () renaming ( _β‰ˆ_ to _β‰ˆα΅‡_ ; refl to β‰ˆα΅‡-refl ; trans to β‰ˆα΅‡-trans )

  -- Magma homomorphisms preserve the binary operation, in curried form.
  hom-preserves-βˆ™ : (h : hom 𝑨 𝑩) (x y : π•Œ[ 𝑨 ])
    β†’ proj₁ h ⟨$⟩ (x βˆ™ y) β‰ˆα΅‡ (proj₁ h ⟨$⟩ x) βˆ™α΅‡ (proj₁ h ⟨$⟩ y)
  hom-preserves-βˆ™ h x y =
    β‰ˆα΅‡-trans  (IsHom.compatible (projβ‚‚ h) {βˆ™-Op} {pair x y})
              (interp-cong 𝑩 βˆ™-Op (Ξ» { 0F β†’ β‰ˆα΅‡-refl ; 1F β†’ β‰ˆα΅‡-refl }))