# Monoids by Mark Seemann

*Introduction to monoids for object-oriented programmers.*

This article is part of a larger series about monoids, semigroups, and related concepts. In this article, you'll learn what a monoid is, and what distinguishes it from a semigroup.

Monoids form a subset of semigroups. The rules that govern monoids are stricter than those for semigroups, so you'd be forgiven for thinking that it would make sense to start with semigroups, and then build upon that definition to learn about monoids. From a strictly hierarchical perspective, that would make sense, but I think that monoids are more intuitive. When you see the most obvious monoid example, you'll see that they cover operations from everyday life. It's easy to think of examples of monoids, while you have to think harder to find some good semigroup examples. That's the reason I think that you should start with monoids.

**Monoid laws**

What do addition (`40 + 2`

) and multiplication (`6 * 7`

) have in common?

They're both

- associative
- binary operations
- with a neutral element.

*monoid laws*. It's worth noting that a monoid is a combination of a data type (or set) and an operation. It's not a data type in itself, but rather a function (or method) that operates on that data type. For example, addition and multiplication are two different monoids that both work on numbers.

**Binary operation**

Let's start with the most basic property. That an operation is *binary* means that it works on *two* values. Perhaps you mostly associate the word *binary* with binary numbers, such as 101010, but the word originates from Latin and means something like *of two*. Astronomers talk about *binary stars*, but the word is dominantly used in computing context: apart from binary numbers, you may also have heard about binary trees. When talking about binary operations, it's implied that both input values are of the same type, and that the return type is the same as the input type. In other words, a C# method like this is a proper binary operation:

public static Foo Op(Foo x, Foo y)

Sometimes, if `Op`

is an instance method on the `Foo`

class, it can also look like this:

public Foo Op (Foo foo)

On the other hand, this isn't a binary operation:

public static Baz Op(Foo f, Bar b)

Although it takes two input arguments, they're of different types, and the return type is a third type.

Since all involved arguments and return values are of the same type, a binary operation exhibits what Eric Evans in Domain-Driven Design calls *Closure of Operations*.

**Associative**

In order to form a monoid, the binary operation must be *associative*. This simply means that the order of evaluation doesn't matter. For example, for addition, it means that

(2 + 3) + 4 = 2 + (3 + 4) = 2 + 3 + 4 = 9

Likewise, for multiplication

(2 * 3) * 4 = 2 * (3 * 4) = 2 * 3 * 4 = 24

Expressed as the above `Op`

instance method, associativity would require that `areEqual`

is `true`

in the following code:

```
var areEqual = foo1.Op(foo2).Op(foo3) == foo1.Op(foo2.Op(foo3));
```

On the left-hand side, `foo1.Op(foo2)`

is evaluated first, and the result then evaluated with `foo3`

. On the right-hand side, `foo2.Op(foo3)`

is evaluated first, and then used as an input argument to `foo1.Op`

. Since the left-hand side and the right-hand side are compared with the `==`

operator, associativity requires that `areEqual`

is `true`

.

In C#, if you have a custom monoid like `Foo`

, you'll have to override `Equals`

and implement the `==`

operator in order to make all of this work.

**Neutral element**

The third rule for monoids is that there must exist a neutral value. In the normal jargon, this is called the *identity* element, and this is what I'm going to be calling it from now on. I only wanted to introduce the concept using a friendlier name.

The identity element is a value that doesn't 'do' anything. For addition, for example, it's zero, because adding zero to a value doesn't change the value:

0 + 42 = 42 + 0 = 42

As an easy exercise, see if you can figure out the identity value for multiplication.

As implied by the above sum, the identity element must act neutrally both when applied to the left-hand side and the right-hand side of another value. For our `Foo`

objects, it could look like this:

var hasIdentity = Foo.Identity.Op(foo) == foo.Op(Foo.Identity) && foo.Op(Foo.Identity) == foo;

Here, `Foo.Identity`

is a static read-only field of the type `Foo`

.

**Examples**

There are plenty of examples of monoids. The most obvious examples are addition and multiplication, but there are more. Depending on your perspective, you could even say that there's more than one addition monoid, because there's one for integers, one for real numbers, and so on. The same can be said for multiplication.

There are also two monoids over boolean values called *all* and *any*. If you have a binary operation over boolean values called *all*, how do you think it works? What would be the identity value? What about *any?*

I'll leave you to ponder (or look up) *all* and *any*, and instead, in the next articles, show you some slightly more interesting monoids.

- Strings, lists, and sequences as a monoid
- Money monoid
- Convex hull monoid
- Tuple monoids
- Function monoids
- Endomorphism monoid
- Monoids accumulate

`==`

operator. On the other hand, there's no `Multiply`

method for `TimeSpan`

, because what does it mean to multiply two durations? What would the dimension be? Time squared?
**Summary**

A monoid (not to be confused with a monad) is a binary operation that satisfies the two monoid laws: that the operation is associative, and that an identity element exists. Addition and multiplication are prime examples, but several others exist.

(By the way, the identity element for multiplication is *one* (*1*), *all* is boolean *and*, and *any* is boolean *or*.)

## Comments

Great series! I'm a big fan of intuitive abstractions and composition. Can't wait for the remaining parts.

I first heard of the

Also, a reference to the algebraic origin of this concept is made in the foot note for this sentence:closure propertyin SICP, where it's mentioned that:It's interesting to see this concept come up over and over, although it hasn't been widely socialized as a formal construct to software composition.

This looks like it's going to be a fantastic series - I'm really looking forwards to reading the rest!

So, as we are talking about forming a vocabulary and reducing ambiguity, I have a question about the use of the word

closure, which I think has more than one common meaning in this context.In Eric Evans' "Closure of Operations",

refers to the fact that the operation is "closed" over it's set of possible values - in other words, the set is closed under the operation.closureClosureis also used to describe a function with a bound value (as in the poor man's object").These are two separate concepts as far as I am aware. Also, I suspect that the latter meaning is likely more well known to C# devs reading this series, especially ReSharper users who have come across it's "implicitly captured closure" detection. So, if I am correct, do you think it is worth making this distinction clear to avoid potential confusion?

Sean, thank you for writing. That's a great observation, and one that I frankly admit that I hadn't made myself. In an ideal world, one of those concepts would have a different name, so that we'd be able to distinguish them from each other.

In my experience, I find that the context in which I'm using those words tend to make the usage unambiguous, but I think that you have a good point that some readers may be more familiar with

closureas a captured outer value, rather than the concept of an operation where the domain and the codomain is the same. I'll see if I can make this clearer when I revisit Evans' example.