Actually, for the Cartesian product, we don’t need the full power of monads: applicatives are enough. We could also define p thus:

p as bs = (,) <$> as <*> bs

sequence

If we are happy to work with lists (which implies that all the values have the same type), sequence does just what we want:

> sequence [[1,2],[3,4]]
[[1,3],[1,4],[2,3],[2,4]]

Nondeterministic calculations

Suppose we’re exploring a space: at each step there are several possible directions we could take: storing those as a list seem natural enough. The key insight is that the monad instance chains these steps together naturally.

For example, suppose we’re exploring a set of cells { 1,2,3,...,maxCell } a step at a time, and at each step can either stay still, or move to a neighbour. We could model it thus:

Almost trivial lists

If trivial lists aren’t much fun, let’s consider lists with zero or one elements. Return is easy:

return x = [x]

There are two cases for bind:

[] >>= _ = []
[x] >>= f = f x

and three for join:

join [[x]] = [x]
join [[]] = []
join [] = []

The Kleisli arrow is messy but as long as the values are all singleton lists it will behave as the trivial monad above:

(f >=> g) [x] = [ (f.g) x ]

However as soon as a null list appears, the calculation immediately returns [].

Finally we know that f x must return either [] or [x'] for some x'. Immediately we can see there's a richer structure here: unlike the Trivial monad above we can’t always decompose f into a pure function and return.

Seasoned Haskell programmers will recognize all this as the Maybe monad.10 We define two constructors:

The standard intuition for the Maybe monad is that it represents a calculation which might fail: for example a database query. A chain of such calculations should proceed normally until one fails, at which point the whole calculation fails.

In the context of our nondeterministic search example for the full list monad, this is equivalent to saying that at each step at most one solution can be found.

Other lists

It’s tempting to ask if other subsets of the list monad exist. For example. simply including lists of length 2 seems doomed to fail, because we can easily make lists of length 4: