monadic extension to do-notation

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


On Sun, Feb 7, 2016 at 9:07 AM, Raphael Mu <encryptedredux at gmail.com> 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
> (http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions), 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.

~TJ


More information about the es-discuss mailing list