Iven Marquardt

Posted on

# Abstracting From Nested Monadic Computations w/o Do-Notation

As soon as we work with monads in Javascript we wind up with nested monadic computations, because there is no do-notation as in Haskell or multi-prompt coroutines as in Kotlin. We cannot use generators either, because they are insufficient for the job.

So are we stuck with nested monadic computations in an ad-hoc fashion like the following?

``````// Monad

const arrChain = mx => fm =>
arrFold(acc => x =>
arrAppend(acc) (fm(x))) ([]) (mx);

// auxiliary function

const arrFold = f => init => xs => {
let acc = init;

for (let i = 0; i < xs.length; i++)
acc = f(acc) (xs[i], i);

return acc;
};

const arrAppend = xs => ys =>
xs.concat(ys);

// MAIN

const main = arrChain([1,2]) (x => // nested monadic computation
arrChain([3,4]) (y =>
arrChain([5,6]) (z =>
x === 1
? []
: [x, y, z])));

main; // [2,3,5,2,3,6,2,4,5,2,4,6]
``````

Actually, there is a small improvement. We can treat monadic actions like applicative functors by wrapping them in the context of their corresponding monad:

``````// Monad

const chain3 = chain => tx => ty => tz => fm =>
chain(chain(chain(tx) (x => fm(x)))
(gm => chain(ty) (y => gm(y))))
(hm => chain(tz) (z => hm(z)));

// MAIN

const main = chain3(arrChain) // much more readable
([1,2])
([3,4])
([5,6])
(x => x === 1
? []
: [y => [z => [x, y, z]]]);

main; // [2,3,5,2,3,6,2,4,5,2,4,6]
``````

run code

Given `chain3` we can implement other arity aware combinators and overload them inside a variadic `chainn` to gain more flexibility.

More on this and other FP topics in my course for FP in JS:
A fool's scriptum on functional programming.