Skip to content

Instantly share code, notes, and snippets.

@dypsilon
Last active April 28, 2024 08:52
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dypsilon/6b242998ba3474fc239255d42b28dd02 to your computer and use it in GitHub Desktop.
Save dypsilon/6b242998ba3474fc239255d42b28dd02 to your computer and use it in GitHub Desktop.
Lazy Continuation Monad in JavaScript
const Cont = require('./lazy-continuation');
// pointed version
const c = Cont.of(5) // initial value
.chain((x) => {
return Cont.of(x + 5); // synchronous computation
})
.chain((x) => { // async computation
return new Cont((resolve) => {
setTimeout(() => resolve(x + 15), 500);
});
});
// we hold the whole computation in c right now
// nothing runs until we call run()
c.run(console.log); // result: 25
// same thing with combinators pointfree style
const R = require('ramda');
// lets extract some utility functions for readability
const syncMorphism = x => x + 5;
const syncComputation = x => Cont.of(x + 5);
const asyncComputation = x => {
return new Cont(resolve => setTimeout(() => resolve(x + 15), 500));
}
// compose our program pipeline
const prog = R.pipe(
Cont.of, // lift the value into the continuation
R.map(syncMorphism), // lets test the map function
R.chain(syncComputation),
R.chain(asyncComputation)
)
// run the prog with the inital value of 5
prog(5).run(console.log) // result: 30
class Continuation {
constructor(x) {
this.x = x;
}
}
Continuation.prototype.of = Continuation.of = x => {
return new Continuation((resolve) => resolve(x));
}
Continuation.prototype.chain = function(f) {
const x = this.x;
return new Continuation((resolve) => {
x((res) => f(res).x(res2 => resolve(res2)));
});
};
Continuation.prototype.run = function(f) {
return this.x(f);
};
Continuation.prototype.inspect = function() {
return `Continuation(${this.x})`;
}
// derivations
Continuation.prototype.map = function(f) {
var m = this;
return m.chain(a => m.of(f(a)));
}
Continuation.prototype.ap = function(m) {
return this.chain(f => m.map(f));
}
module.exports = Continuation;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment