When i wanted to make sense of continuations, i started from the basics : Callbacks and after many refactorings, i discovered promises, and finally the mother of all monads as it has been called : The Continuation Monad.

lets say you have a simple function

const square = x => x * x ;

console.log(square(4)); // prints 16

Part 1

1) Use Callback and remove return type

you can pass a callback and remove the return type. This the famous Continuation-passing style

const square= (x,callback)=>callback(x*x);

square(4,console.log); // prints 16

and you can compose functions with callbacks like this :

const square = (x,callback)=>callback(x*x);

square(2,

x=>square(x,console.log)); // prints 16

which of course leads to callback hell which is special case of the arrow anti-pattern…

2) Curry the Callback

What if we curry the action and return it as a result ?! we could do this :

const square = (x)=>callback=>callback(x*x);



if you look at this for a long time and rename callback to resolve you will see that this is actually resembles a promise. And use it like this:

square(4)(y=>console.log(y)); // prints 4

[Side Note : we could make it into a Promise if we enclose the callback into an object that exposes a then function like that :

const square = (x)=>callback=>callback(x*x);// transform it into const square = (x)=>({then:resolve=>resolve(x*x)}); square(2).then(r=>console.log(r))

End of side Note]

it looks a bit better but we can do a few more refactoring moves. This return type of callback=>callback(x*x) is actually (int → ⊥) → ⊥where ⊥ is the intitial object /empty type /false. This says, if you give me a function that takes an int i and returns nothing (int → ⊥) i will do something with it and then return nothing (int → ⊥) → ⊥.

3) Generalize the returned Continuation

what if we wanted to generalize this and instead of ⊥ return an arbitrary type T. Then we should have :

(int → T) → T :

This says, if you give me a function that takes an int i and gives a T i will do something with it and return T which is an extension of

(int → ⊥) → ⊥

Because we use untyped javascript this is not of concern but with a strong type js language extension like Typescript ,we would need to actively pay attention to this point.

This function signature (U→ T) → T is kind of famous, and we can call it Continuation

Part 2

If we want to go a step further, then Monads come in. This part is a bit more tricky, just follow along. We can form a Monad from this Continuation type (U→ T) → T which is the callback=>callback(x*x). For all those who do not know what monad is:

Functor is a container. List is the most known Functor for example. Here is the Continuation (U→ T) → T. we can view it as a container of U.

is a container. List is the most known Functor for example. Here is the Continuation Endofunctor is a functor from a category to itself. In this case a continuation (A→ T) → T that can transform to an other continuation (B→ T) → T both are in the same category of Continuations so this is an Endofunctor.

is a functor from a category to itself. In this case a continuation that can transform to an other continuation both are in the same category of so this is an Endofunctor. Monoid is a structure with a binary operation ∘ and an identity element Id. In a sense, figure out how to “multiply (combine) continuations” somehow like ((A→ T) → T) ∘ ((B→ T) → T)

The thing you have to remember is that Monads have two operations :

c → T(c) //Return T(T(c))→ T(c) //join

1)In this first operation c → T(c) we can start from an object C and get an container T(c).

2)The second one T(T(c))→ T(c) means that we can join/flatten the two containers in one.

4) Extract the Continuation Structure

Now we only need to extract the Continuation mechanism from the square function so we could reuse it. So we can have the first part of the Monad, the Return c → T(c), which is the wrapping of the value with a continuation, like this :

in order to finally get the Continuation monad we have to Add the Bind Method: T (A) → (A → T (B)) → T (B) that composes continuations. This is by far the most difficult part to comprehend and you cannot really grasp it if you don’t try to build it on your own one time.

if we replace T that is the Monad with (A→ T) → T in this

T (A) → (A → T (B)) → T (B)

we get something ridiculous like this in Type form

((A→ T) → T)→( A→((B→ T) → T))→ ((B→ T) → T)

This says : “if you give me a continuation for A [(A→ T) → T] and a function that takes an A and gives a continuation for B [ A→((B→ T) → T)] then i can give you a continuation for B [(B→ T) → T]”

one can meditate on why the bind method below works its like a js zen koan when you grasp it becomes obvious .

var bind = (cont1, func)=>(callback=>cont1(contResult=>func(contResult)(callback)));

ok let me try to explain it. If you reached here congratulations by the way.

ok we have a cont1 (A→ T) → T and a func A→((B→ T) → T) we want to return (B→ T) → T . So we first write callback=> which is (B→ T), the rest of this should return a value T . How are we going to get this value . well we can take it from cont1 =(A→ T) → T just pass a function inside that takes an argument A named contResult. ok untill now we have

bind = (cont1, func)=>(callback=>cont1(contResult=>

… can you see the rest ???

This will conclude the construct. Look the result tab at this js Fiddle bellow :

In Summary :

Starting from an initial Function

const f = x => x * x ;

console.log(f(4)); // prints 16

2. Use Callback and remove the return type

const f1 = (x,callback)=>callback(x*x);

3. Curry the Callback

const squareCont = (x)=>callback=>callback(x*x);

5. Extract the Continuation Structure Also Known As the Return Method of the monad

const toCont=v=>callback=>callback(v); toCont(x=>x*x)

(y=>toCont(y(4))

(t=>console.log(t)));

6. Add The bind Monadic method and thus Complete the Monad

var bind = (cont1, func)=>(callback =>cont1(contResult=>func(contResult)(callback)));

Have a question? Just leave a comment below.

Do you want to go one step further ? Read how you can go from promises to Asynchronous Functional error handling

Read more :

feel free to connect with me in LinkedIn