monadic extension to do-notation

Tab Atkins Jr. jackalmage at
Tue Feb 9 20:27:19 UTC 2016

On Sun, Feb 7, 2016 at 9:07 AM, Raphael Mu <encryptedredux at> wrote:
> The ES Promise is an instance of Monad, a property that implies a much more
> concise and expressive syntax for using Promise, by exploiting its monadic
> properties. I've seen a lot of people complain about Promises having too
> clumsy a syntax, and likewise for async/await.

As others have said, ES Promise is monad-like, but not actually a
monad, because it flattens too much.  That said, it's close enough for
most purposes.

> We now have the do-notation proposal
> (, and
> monadic assignment would fit well into the syntax.

I assume you're reading this as being similar to do-notation in
Haskell?  The resemblance stops at the keyword - the do-notation in ES
is just a way of converting a statement (or multiple) into an
expression.  Do-notation in Haskell is specifically and explicitly
sugar for nested bind calls.  Conflating them will likely just lead to
sadness (Rick offers an example with a syntax conflict).

In any case, arrow functions actually make nested binds not too bad in JS:

let finalPromise =
  promiseA.then( x =>
  promiseB.then( y => {
  let c = f(a,b);
  g(a, b, c);

Except for the fact that you need to track the parens/curlies you
used, so you can close them at the end, this hews pretty close to
Haskell's do-notation.

As an added benefit, you get support for
functors/applicatives/tranversables/etc for free, by using .map/etc
instead of .then (/.flatMap/.bind, for the general monad).  Also,
being able to customize the function used is nice for JS-as-it-exists,
because we don't have a rich ecosystem of monadic/etc classes that use
a common syntax yet: Promises use .then, Arrays have a proposal to add
.flatMap, JS Fantasy Land uses .chain, etc.

> The extension would allow use of `<-` within a do-expression for binding
> Promise values to variables, and the computation would behave most similarly
> to the Either monad in Haskell (in the following code, if promiseA or
> promiseB reject, the result of the entire expression would be a rejected
> Promise).

Even if we added explicit support for something like this, there'd be
no reason to specialize it to Promises.  It would just desugar to
nested binds, same as Haskell.


More information about the es-discuss mailing list