Note: While this is public, this is mostly written for my own sake, to better understand these concepts in relation to their pure mathematical foundations. Comments and suggestions welcome!
This gist aims to give a brief overview of certain mathematical objects and why programmers care about them. The overall structure for each section will start with a definition for the object, then a few examples, followed by a list of properties that makes the object useful/interesting to programmers.
Some additional notes for this gist:
- Basic proof-reading and some mathematical maturity is assumed for the definitions.
- All of the examples use OCaml-style notation, although it shouldn't matter too much if you're unfamiliar with OCaml.
- We treat programming types as sets, i.e.
int
is the same as$\mathbb{Z}$ .- Many of the definitions denote sets using
$T$ for "type".
- Many of the definitions denote sets using
A monoid is a set equipped with an associative binary operation and an identity element. More concretely, suppose we have:
- Some set
$T$ - Some binary operator
$\cdot\colon T\times T\to T$
This forms a monoid if for all
and there exists some
For brevity, we write this monoid as
Consider the monoid
and
Let
and the empty string
Prototypical monoid for this section:
-
List computation: Since addition is closed (i.e. adding two
int
s yields anotherint
), we can apply the$+$ operator to an arbitrary number ofint
s (i.e. alist
ofint
s), instead of just two. We do this by continually applying$+$ between our current sum and the next value in thelist
, until we have summed up the entirelist
.-
Note: Since our operator takes in two arguments, what value should we
start with for computation? Remember that monoids contain an identity
element; in the case of summing
int
s, we can start with the value 0. -
Note: This is sometimes called "reducing", since we can reduce a
list
ofint
s to a singleint
via repeated application of$+$ .
-
Note: Since our operator takes in two arguments, what value should we
start with for computation? Remember that monoids contain an identity
element; in the case of summing
-
Incremental computation: Again, since addition is closed, we can
incrementally compute the sum of
int
s. If we have a current sum and are given moreint
s to add, we don't have to recompute anything; we can simply add to our existing sum. -
Parallel computation: Since addition is associative, we can perform it in
any arbitrary order. This lends itself very well to parallelizing the
computation, since multiple cores can add parts of the
list
simultaneously, before the partial sums are added together.
Note: Combinations of monoids are also monoids! For example, consider the
monoids int * string
forms a monoid, by defining a binary operation
and identity element pairwise. Let
we get the monoid