DEV Community

Iven Marquardt
Iven Marquardt

Posted on

Monads naturally arise from continuations

A function const id = x => x becomes a continuation passing style function in Javascript as soon as you add a function argument and call it with the result value in tail position: const id_ = x => k => k(x). The actual continuation emerges when you apply the CPS function: id_(2) yields const id2 = k => k(2), the continuation.

You can compose normal functions with const comp = f => g => x => f(g(x)) and then comp(id) (id). But can you compose continuations like id2 as well?

// doesn't work, cont2 returns a value but cont expects a fun
const comp_ = cont => cont2 => k => cont(cont2(k));

// works but x is awkwardly discarded
const comp_ = cont => cont2 => k => cont2(x => cont(y => k(y));
Enter fullscreen mode Exit fullscreen mode

Unfortunately, no. There is no specialized comp_ operator for id2 to compose two continuations in a general way. But there is a way to compose the CPS version id_ with its continuation id2:

const comp_ = cont => cps => k => cont(x => cps(x) (k));
const f = comp_(id2) (id_);
f(id); // yields 2 since we are only composing identity
Enter fullscreen mode Exit fullscreen mode

comp_ a.k.a. chain/bind is one part of the monad interface. The second one is const of = x => k => k(x), which simply puts a normal value into the monad context:

const chain = cont => cps => k => cont(x => cps(x) (k));
const of = x => k => k(x);
const f = chain(of(3)) (id_);
f(id); // yields 3
Enter fullscreen mode Exit fullscreen mode

So not just the continuation monad but monads of all types are just the most general way to compose/chain expressions of those types using continuations under the hood. Please note that monads are a very generalized and thus subtle concept. Stare at it long enough, play with it once in a while and you'll eventually get it.

Top comments (0)