I’m writing a book. It’s called JavaScript Testing Recipes.

Following on from my introduction to monads in JavaScript, and before I get into how they apply to asynchronous programming, I’d like to take a quick detour to improve the usability of the tools we’ve built up. Recall we have a function for composing functions:

``````var compose = function(f, g) {
return function(x) { return f(g(x)) };
};``````

We have some ‘debuggable’ functions:

``````// sine :: Number -> (Number,String)
var sine = function(x) {
return [Math.sin(x), 'sine was called.'];
};

// cube :: Number -> (Number,String)
var cube = function(x) {
return [x * x * x, 'cube was called.'];
};``````

And finally we have the unit and bind functions for the ‘debuggable’ monad:

``````// unit :: Number -> (Number,String)
var unit = function(x) { return [x, ''] };

// bind :: (Number -> (Number,String)) -> ((Number,String) -> (Number,String))
var bind = function(f) {
return function(tuple) {
var x  = tuple[0],
s  = tuple[1],
fx = f(x),
y  = fx[0],
t  = fx[1];

return [y, s + t];
};
};``````

These let us compose our debuggable functions to create new debuggable functions:

``````var f = compose(bind(sine), bind(cube));
f(unit(3)) // -> [0.956, 'cube was called.sine was called.']``````

This is all well and good, but we should really be able to compute sin(x^3) as a one-liner. With the code we have, this expression would be:

``bind(sine)(bind(cube)(unit(3)))``

This is hardly convenient, especially when I tell you that the equivalent Haskell expression is:

``return 3 >>= cube >>= sine``

This reads like a pipeline: take 3, pass it through cube, then pass the result of that through sine. In Haskell, unit is called return, and bind is actually an operator (or infix function) called >>=. The operator >>= doesn’t just convert functions into composable form, it takes a monadic value – in our example, a (Number,String) tuple – and a debuggable function, and deals with unpacking the value from the monad, applying the function to it, and combining the result with the monad in a meaningful way.

Using our existing names, a direct translation to JavaScript of this would be:

``bind( bind( unit(3), cube), sine)``

Where the bind function now looks like this:

``````// bind :: (Number,String) -> (Number -> (Number,String)) -> (Number,String)
var bind = function(x, f) {   //  e.g. x = [3, ''], f = cube
var y  = x[0],              //           3
s  = x[1],              //           ''
fy = f(y),              // cube(3) = [27, 'cube was called.']
z  = fy[0],             //           27
t  = fy[1];             //           'cube was called.'

return [z, s + t];
};``````

This representation is clearer, but not quite as expressive as the Haskell version. Let’s go one step forward:

``var y = pipe(unit(3), [cube, sine])``

This seems reasonably close to Haskell’s version, and to go any further we’d really need some syntactic abstractions that JavaScript does not have. This pipe function is straightforward to implement: it takes a monadic value, and uses bind to pipe it through the list of debuggable functions:

``````// pipe :: (Number,String) -> [Number -> (Number,String)] -> (Number,String)
var pipe = function(x, functions) {
for (var i = 0, n = functions.length; i < n; i++) {
x = bind(x, functions[i]);
}
return x;
};``````

We can easily use this with anonymous inline functions without losing much expressiveness:

``````var z = pipe(unit(7), [ function(x) { return [x+1, 'inc.'] },
function(x) { return [2*x, 'double.'] },
function(x) { return [x-1, 'dec.'] }
])

// z == [15, 'inc.double.dec.']``````

Here we’ve calculated (2 * (7 + 1)) - 1 using fairly direct syntax, where the operations and the log messages are nicely separated. If you’ve done a lot of asynchronous programming, this will probably be starting to look somewhat familiar, and indeed I’ll be showing where this leads in the next article.

## 10 thoughts on “Monad syntax for JavaScript”

1. Andrew says:

Seems like function chaining (as in jQuery) is the most idiomatic Javascript approach to pipelining. It’s not syntactically identical with what you’re thinking about but i think it’s the closest thing in terms of approach.

2. Method chaining is one approach, and I can see why you’d think it’s an obvious solution here. I realize this is a contrived example, but I’m just trying to use something simple to demonstrate a pattern that can be used to solve much more complex problems. I’ll try to expand on this in my next post.

3. Mark P Sullivan says:

I think you need to s/3/x/ a couple times starting at the line: “bind(sine)(bind(cube)(unit(3)))”.

4. Developing In Javascript | Aquilent Blog

5. MySchizoBuddy says:

6. Sintaxis de mónadas para JavaScript

7. Las Promesas son las mónadas de la programación asíncrona

9. john slater says:

for the version of bind you use in
bind( bind( unit(3), cube), sine)

// bind :: (Number,String) -> (Number -> (Number,String)) -> (Number,String)

I think it should be
// bind :: ((Number,String),(Number -> (Number,String))) -> (Number,String)