5 ms·
The Delimited Continuation Monad in JavaScript (2014)
- danharaj 9y agoI would run away and never look back if I saw someone using delimited continuations without types to ensure that values and continuations match up at all call sites. There is no trickier control flow.
- signalsmith 9y agoEvery time I see someone discussing Monads in JavaScript without _mentioning_ Promises, I pause a bit. To my eyes, aside from a bit of type-juggling which makes Haskell programmers break out in cold sweats, Promises and Monads are similar enough. The main difference is that .bind()/.then() implicitly converts (a -> b) to (a -> M b) - i.e. if the function you pass to .bind()/.then() does not return a Promise/Monad as it should, it's converted. Promise.create() does something similar. This level of type-juggling is not weird for a dynamically-typed language. So my question is: rather than attempting to define your own Monads that are more type-strict than the language itself, how many of the behaviours in this article can be implemented by extending Promise.prototype instead? Promise.prototype.binary = function (right, binaryFn) { return this.then(leftVal => Promise.resolve(right).then(rightVal => binaryFn(leftVal, rightVal) ) ); }; onePromise.binary(twoPromise, (a, b) => a + b); // Adds two promises together
- chowells 9y agoThat sort of works, in the http://blog.sigfpe.com/2008/12/mother-of-all-monads.html http://blog.sigfpe.com/2008/12/mother-of-all-monads.html sense. Promises are an awkward encoding of continuations, and so they can encode all monadic structures. It sort of misses the point, though in a way which Javascript is incapable of expressing. Namely, that the principle of least power is a good thing, and you should restrict yourself to contexts which make only the operations you want accessible.
- jdonaldson 9y agoI had a big problem with the automatic conversion on return values. This is like saying that Promise<Promise<String>> can't exist, only Promise<String>. This reminds me of when Perl disallowed Array<Array<String>>, insisting that only Array<String> was necessary. The second drawback to this autoconversion approach is that it enforces a very specific runtime behavior, and requires drawing a line for compliant/non-compliant libraries. I remember reading the github discussion threads marveling at how they were at once dividing the community and crippling such an important feature.
- algesten 9y agoYou mean this thread? https://github.com/promises-aplus/promises-spec/issues/94 https://github.com/promises-aplus/promises-spec/issues/94 I love reading the for-against monadic promises. It actually is educating just following the discussion.
- jdonaldson 9y agoYep, that's the one. I think it should be required reading. Most of the folks in that thread are highly intelligent, and mean well. But to hear them toss out category theory as "impractical" and "not based in reality"?... It's just so cringeworthy. Here's their final spec, which seems absolutely convoluted to me: https://promisesaplus.com/#the-promise-resolution-procedure https://promisesaplus.com/#the-promise-resolution-procedure Why does any of this matter to non-js devs (like me)? Because some of us want to target javascript with higher level languages, and externing a js promise instance is a necessity. The runtime-driven behavior described here means that the compiler will never really know the type of a given promise resolution. So, the compiler is very limited in what it can handle.