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));
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
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
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)