Concepts: Monoid

1. Motivation

The Monoid interface provides a consumer that functions as an identity consumer. Like the identity function, {identity,12:3}, this identity consumer is useful in a number of cases. Most often it is useful as the initial value when reducing over a list of consumers and is used as such in the definition of expandAll {chain-expandAll-implementation,6:2}.

2. Details

The interface of monoid is defined as follows.

{types/Monoid.js 2}
export type Monoid<Static, State> = {
  empty: () => (State, Static) => State,
  identity: (State, Static) => State
};

The interface has two generic parameters, and the State parameter does not change from input to output. This is what tells Flow that this is an identity function and cannot modify its input. The empty method also takes no input, and so must always return the same consumer. The empty method is defined and required by the static-land specification. However using it like that can be a bit of a pain. I've included the identity property, which is just the result of calling the empty method.

There are some laws that the Monoid implementation needs to follow with respect to the Semigroup concat function. These are simply the right and left identity laws. Concatenating the result of empty with any other consumer is the same as just using that consumer directly.

{monoid-right-identity 2}
concat(c, empty()) === c
{monoid-left-identity 2}
concat(empty(), c) === c

The implementation is almost trivial. The state is simply returned, and the static part is ignored. In order to satisfy Javascript scoping requirements, the actual consumer is stored in identity and empty simply references it.

{monoid-implementation 2}
empty: () => MonoidI.identity,
identity: (s, _) => s

I wrap it all up in a module.

{Monoid.js 2}
{import-types-monoid, 3}

const MonoidI : Monoid<*, *> = {
  {monoid-implementation, 2}
};

export default MonoidI;

3. Imports

The Monoid type needs to be imported.

{import-types-monoid 3}
import type { Monoid } from './types/Monoid';

Used in section 2

Some modules need to import the Monoid interface.

{import-monoid 3}
import Monoid from './Monoid';

Used in sections 7:2, 12:1 and 12:2


Previous ChapterNext Chapter