Monoids: Semigroups with an Identity Element
A Monoid is an algebraic structure that builds directly upon the concept of a Semigroup. It starts with the same requirements:
- A non-empty set (in programming terms, a Type, let’s call it
'a'
). - A binary operation
•
(in programming, a function of type'a -> 'a -> 'a
) that is closed over the type'a'
. - This operation
•
must be associative:(x • y) • z = x • (y • z)
for allx, y, z
of type'a'
.
And then adds one crucial additional requirement:
- There must exist an identity element
e
(also of type'a'
) within the setA
(our Type'a'
) such that for every elementx
of type'a'
:e • x = x
(left identity)x • e = x
(right identity)
In simpler terms, a monoid is a semigroup that possesses an identity element for its binary operation. All the benefits of associativity from semigroups still apply, but now we also have a special “neutral” element.
Examples of Monoids
Section titled “Examples of Monoids”Let’s revisit our familiar examples and see which ones form monoids:
-
Integers with Addition:
- Type (Set):
int
- Binary Operation:
(+)
(typeint -> int -> int
), which is associative. - Identity Element:
0
(typeint
), since0 + x = x
andx + 0 = x
. - Therefore, (
int
,(+)
,0
) is a monoid.
- Type (Set):
-
Integers with Multiplication:
- Type (Set):
int
- Binary Operation:
(*)
(typeint -> int -> int
), which is associative. - Identity Element:
1
(typeint
), since1 * x = x
andx * 1 = x
. - Therefore, (
int
,(*)
,1
) is a monoid.
- Type (Set):
-
Strings with Concatenation:
- Type (Set):
string
- Binary Operation:
(+)
for strings (typestring -> string -> string
), which is associative. - Identity Element:
""
(the empty string, typestring
), since"" + s = s
ands + "" = s
. - Therefore, (
string
,(+)
for concatenation,""
) is a monoid.
- Type (Set):
-
Booleans with Logical OR:
- Type (Set):
bool
- Binary Operation: Logical OR (let’s denote
||
), which is associative ((p || q) || r = p || (q || r)
). - Identity Element:
false
, sincefalse || p = p
andp || false = p
. - Therefore, (
bool
,||
(OR),false
) is a monoid.
- Type (Set):
-
Booleans with Logical AND:
- Type (Set):
bool
- Binary Operation: Logical AND (let’s denote
&&
), which is associative ((p && q) && r = p && (q && r)
). - Identity Element:
true
, sincetrue && p = p
andp && true = p
. - Therefore, (
bool
,&&
(AND),true
) is a monoid.
- Type (Set):
Constructing Monoids from Semigroups
What about our physical examples like LEGO blocks or USB devices, which formed semigroups but seemed to lack natural identity elements?
Mathematically, it’s often possible to extend a semigroup to form a monoid by formally “adjoining” an identity element if one doesn’t already exist within the original set. For instance:
- LEGO blocks: We could define a “virtual empty block”
e_lego
such that connectinge_lego
to any blockX
(orX
toe_lego
) results inX
. In a CAD system or a game, thise_lego
could be a perfectly valid concept, allowing the (LEGO blocks +e_lego
, join operation,e_lego
) system to be treated as a monoid. - USB devices: Similarly, a “virtual null-port hub” could act as an identity for USB connections in a simulation.
This doesn’t mean every semigroup is a monoid in its original form, but it highlights that the monoid structure (associativity plus identity) is a very common and useful pattern that can sometimes be achieved by augmenting a semigroup with a suitable identity concept. The key is whether such an identity element makes sense and behaves correctly within the context of the set and operation.
Why Monoids Matter
Section titled “Why Monoids Matter”The addition of an identity element to the associative binary operation of a semigroup provides significant advantages in programming:
- All benefits of a Semigroup: We retain the crucial property of associativity, which allows for flexible grouping of operations and is key for tasks like parallel computation or efficient folding/reduction of sequences.
- A “Neutral” Starting Point / Default Value: The identity element provides a natural “zero” or “empty” or “default” value for the operation. This is extremely useful:
- When reducing a collection of items: if the collection is empty, the identity element is the sensible result (e.g., sum of an empty list of numbers is
0
, product is1
, concatenation of an empty list of strings is""
). - As an initial value for accumulators in folds or loops.
- For representing a default or an “un-effected” state.
- When reducing a collection of items: if the collection is empty, the identity element is the sensible result (e.g., sum of an empty list of numbers is
This combination of an associative binary operation and an identity element makes monoids a very powerful and frequently encountered pattern in functional programming, especially when dealing with aggregation, combination, or processing sequences of data.