1. 4
  1.  

  2. 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)