1. 4
    1. 3

      Very well written! A few basically inconsequential reading notes:

      • The List data type need not be lazy to have a monad, although it will obviously feel more Haskell like that way and lets one talk about generators, I suppose.
      • Promises are significantly more than just the continuation monad. It’s easy enough to describe, though, except we’ll have to be rid of the idea that the constructor itself is unit.

      A value of type Cont is just a wrapper around a function which knows what to do with a continuation.

      function Cont(contHandler) {
        this.contHandler = contHandler;
      };
      

      For unit, this function merely passes the value to the continuation. Easy!

      Cont.unit = function(value) {
        return new Cont((continue) => continue(value));
      };
      

      We “eliminate” Cont values by providing a continuation to be passed to the wrapped continuation handler.

      Cont.prototype.run = function(resume) {
        return this.contHandler(resume);
      };
      

      The most natural way to run a Cont is to pass it a continuation which doesn’t do anything—it just returns immediately.

      Cont.prototype.escape = function() {
        return this.run((x) => x);
      };
      

      Binding is more complex. We’ll first consider a weird kind of identity on Conts. It’s quite convoluted, but you can see it does nothing more than construct a new Cont via a handler which runs the current Cont passing the provided continuation.

      Cont.prototype.doNothing = function () {
        return new Cont((resume) => this.run((value) => resume(value)));
      };
      

      which can be written in a less convoluted way as follows

      Cont.prototype.doNothing = function () {
        return new Cont((resume) => this.run(resume));
      };
      

      Finally, we’ll construct bind by a slight modification of the convoluted form of doNothing where we slip the transform function in at just the right time

      Cont.prototype.bind = function (transform) {
        return new Cont((resume) => this.run((value) => transform(value).run(resume)));
      };
      

      Notice that all we do is pass the value to transform which gives us a new Cont which we can immediately .run using the original continuation resume.

      (Here it is in de-ES6’d, copy-and-pasteable form: https://gist.github.com/tel/9a34caf0b6e38cba6772)