module Algebra.Semigroup where
private variable
: Level
ℓ ℓ₁ : Type ℓ A
Semigroups🔗
record is-semigroup {A : Type ℓ} (_⋆_ : A → A → A) : Type ℓ where
A semigroup is an associative magma
, that is, a
set equipped with a choice of associative binary operation
⋆
.
field
: is-magma _⋆_
has-is-magma : {x y z : A} → x ⋆ (y ⋆ z) ≡ (x ⋆ y) ⋆ z
associative
open is-magma has-is-magma public
open is-semigroup
To see why the set truncation is really necessary, it helps to explicitly describe the expected structure of a “∞-semigroup” in terms of the language of higher categories:
An ∞-groupoid
A
, equipped withA map
_⋆_ : A → A → A
, such that⋆
is associative: there exists an invertible 2-morphismα : A ⋆ (B ⋆ C) ≡ (A ⋆ B) ⋆ C
(called the associator), satisfyingThe pentagon identity, i.e. there is a path
π
(called, no joke, the “pentagonator”) witnessing commutativity of the diagram below, where all the faces areα
:
- The pentagonator satisfies its own coherence law, which looks like the Stasheff polytope and so on, “all the way up to infinity”.
By explicitly asking that A
be truncated at the level of
sets, we have that the associator automatically satisfies the pentagon
identity - because all parallel paths in a set are equal. Furthermore,
by the upwards closure of h-levels, any further coherence condition you
could dream up and write down for these morphisms is automatically
satisfied.
As a consequence of this truncation, we get that being a semigroup operator is a property of the operator:
: {_⋆_ : A → A → A} → is-prop (is-semigroup _⋆_)
is-semigroup-is-prop .has-is-magma =
is-semigroup-is-prop x y i (x .has-is-magma) (y .has-is-magma) i
is-magma-is-prop {_⋆_ = _⋆_} x y i .associative {a} {b} {c} =
is-semigroup-is-prop .has-is-set (a ⋆ (b ⋆ c)) ((a ⋆ b) ⋆ c) (x .associative) (y .associative) i
x
instance
: ∀ {_*_ : A → A → A} {n} → H-Level (is-semigroup _*_) (suc n)
H-Level-is-semigroup = prop-instance is-semigroup-is-prop H-Level-is-semigroup
A semigroup structure on a type packages up the
binary operation and the axiom in a way equivalent to a structure
.
: Type ℓ → Type ℓ
Semigroup-on = Σ (X → X → X) is-semigroup Semigroup-on X
Semigroup-on
is a univalent
structure, because it is equivalent to a structure expressed as a structure description
. This is only the
case because is-semigroup
is a
proposition, i.e. Semigroup-on
can
be expressed as a “structure part” (the binary operation) and an “axiom
part” (the associativity)!
module _ where
private
: Str-desc ℓ ℓ (λ X → (X → X → X)) ℓ
sg-desc .Str-desc.descriptor = s∙ s→ (s∙ s→ s∙)
sg-desc .Str-desc.axioms X = is-semigroup
sg-desc .Str-desc.axioms-prop X s = is-semigroup-is-prop
sg-desc
: Structure ℓ (Semigroup-on {ℓ = ℓ})
Semigroup-str = Desc→Str sg-desc
Semigroup-str
: is-univalent (Semigroup-str {ℓ = ℓ})
Semigroup-str-is-univalent = Desc→is-univalent sg-desc Semigroup-str-is-univalent
One can check that the notion of semigroup homomorphism generated by
Semigroup-str
corresponds exactly
to the expected definition, and does not have any superfluous
information:
module _
{A : Type} {_⋆_ : A → A → A} {as : is-semigroup _⋆_}
{B : Type} {_*_ : B → B → B} {bs : is-semigroup _*_}
{f : A ≃ B}
where
_ : Semigroup-str .is-hom (A , _⋆_ , as) (B , _*_ , bs) f
( (x y : A) → f .fst (x ⋆ y) ≡ (f .fst x) * (f .fst y))
≡ _ = refl
The “min” semigroup🔗
An example of a naturally-occurring semigroup are the natural numbers
under taking minimums
.
open import Data.Nat.Properties
open import Data.Nat.Order
open import Data.Nat.Base
: is-semigroup min
Nat-min .has-is-magma .is-magma.has-is-set = Nat-is-set
Nat-min .associative = min-assoc _ _ _ Nat-min
What is meant by “naturally occurring” is that this semigroup can not
be made into a monoid: There is no natural number unit
such
that, for all y
, min unit y ≡ y
and
min y unit ≡ y
.
private
: (unit : Nat) → ¬ ((y : Nat) → min unit y ≡ y)
min-no-id =
min-no-id x id let
: suc x ≤ x
sucx≤x = subst (λ e → e ≤ x) (id (suc x)) (min-≤l x (suc x))
sucx≤x in ¬sucx≤x x sucx≤x
Constructing semigroups🔗
The interface to Semigroup-on
is
contains some annoying nesting, so we provide an interface that arranges
the data in a more user-friendly way.
record make-semigroup {ℓ} (A : Type ℓ) : Type ℓ where
field
: is-set A
semigroup-is-set _⋆_ : A → A → A
: ∀ x y z → x ⋆ (y ⋆ z) ≡ (x ⋆ y) ⋆ z
⋆-assoc
: is-semigroup _⋆_
to-is-semigroup .has-is-magma .is-magma.has-is-set = semigroup-is-set
to-is-semigroup .associative = ⋆-assoc _ _ _
to-is-semigroup
: Semigroup-on A
to-semigroup-on .fst = _⋆_
to-semigroup-on .snd = to-is-semigroup
to-semigroup-on
open make-semigroup using (to-is-semigroup; to-semigroup-on) public