Hacker News new | ask | show | jobs
by skwosh 3956 days ago
Apologies in advance for the unsolicited monad tutorial (it's my turn to be that asshole)...

Firstly, saying "`X` is a monad" is the same as saying "class `X` implements the monad interface".

The monad interface is usually defined with `return` and `bind`, but I think it's more instructive to borrow the terminology from JavaScript's `Promise`...

* `Promise#resolve(value)` is the same as `return`, also known as `pure`. It just wraps the given value in a promise.

* `Promise#then(function)` combines both `bind` (when a new Promise is constructed and returned) and the functor method `map` (when a plain value is returned).

To provide a unified monad/functor interface for both `Promise` and `Array` (using `wrap` instead of `resolve):

    // `then` provides both `bind` and `map` depending on the return type of the given function:
    Promise.prototype.map = Promise.prototype.then 

    Promise.wrap = Promise.resolve

    // f maps elements to arrays of elements:
    Array.prototype.then = function (f) {
        return [].concat.apply ([], this.map(f))
    }

    Array.wrap = function (x) {
        return [x]
    }
There's no intrinsic value beyond that shared interface, it just allows you to write abstractions without knowing specifically what kind of monad you're dealing with (like the "do" syntax).

EDIT: BTW, I've purposely skipped a few things in this description, it's meant to be illustrative, not definitive...