Here’s our definition of a monoid, slightly modified so you have to invoke the property 1 to get the identity element:
var monoidOf = function (m, n) { n = n || m; func(m); func(n); return makeInterface({ '*': hom([m, m], n), 1: hom([], n) }); };
Here’s a slight variant of this definition of a monoid:
var monadOf = function (m, n) { n = n || m; func(m); func(n); return function (intr) { return function (t) { return makeInterface({ '*': hom([m(m(t))], n(t)), 1: hom([t], n(t)) })(intr); }; }; };
Instead of the multiplication expecting a pair of functions, it expects the composite of functions. Here’s one way it’s used:
var flatten = monadOf(arrOf)({ '*': function (arrayOfArrays) { var flattened = [], len = arrayOfArrays.length; for (var i = 0; i < len; ++i) { var innerLen = arrayOfArrays[i].length; for (var j = 0; j < innerLen; ++j) { flattened.push(arrayOfArrays[i][j]); } } return flattened; }, 1: function (x) { return [x]; } }); var stringFlatten = flatten(str);
The stringFlatten example’s multiplication expects a doubly nested array of strings and returns an array of strings. It’s associative, in the sense that if you have a triply-nested array, it doesn’t matter if you flatten the inner or outer layer first. It’s unital in the sense that if you wrap a list in brackets and then flatten it, you get the same thing back; similarly if you wrap each element in brackets and flatten it, you also get the same thing back.
In a monoid, the multiplication wants two things and returns one; in a monad, the multiplication wants a functor applied twice to t
and returns the functor applied once to t
. In a monoid, the unit wants no elements and returns one; in a monad, the unit wants a functor applied no times to t
and returns the functor applied once to t
.
Monads are an exceptionally versatile design pattern. There are monads for lists, exceptions, simulating imperative programming on top of functional programming but still keeping the state explicit so you can mock out the state for easy testing, continuation passing style, parsing, promises (aka futures), event chaining, and more. jQuery, for example, is the combination of several of these monads.
Leave a Reply