Skip to content

Instantly share code, notes, and snippets.

@mandel59
Last active August 29, 2015 14:27
Show Gist options
  • Save mandel59/5c5d1961ef10a9f65666 to your computer and use it in GitHub Desktop.
Save mandel59/5c5d1961ef10a9f65666 to your computer and use it in GitHub Desktop.
Monads in JavaScript
/*
class Functor<F(_)>
map : <A>(g: A => B) => (F(A) => F(B))
*/
function Functor(f) {
this.map = f;
}
/*
class Monad<F(_)>
T : Functor<F>
μ : <A>(x: F(F(A))) => F(A)
η : <A>(x: A) => F(A)
*/
function Monad(m) {
this.T = m.T;
this.μ = m.μ;
this.η = m.η;
}
Monad.prototype.bind = function(m, k) {
return this.μ(this.T.map(k)(m));
}
var IdentityFunctor = new Functor((g) => (x) => g(x));
var IdentityMonad = new Monad({
T: IdentityFunctor,
μ: (x) => x,
η: (x) => x,
});
var ArrayFunctor = new Functor((g) => (x) => [for(y of x) g(y)]);
var ArrayMonad = new Monad({
T: ArrayFunctor,
μ: (x) => [for(y of x) for(z of y) z],
η: (x) => [x],
});
ArrayMonad.bind([1, 2, 3], (x) => [x + 10, x * 100]);
var FunctionFunctor = new Functor((g) => (f) => (x) => g(f(x)));
var FunctionMonad = new Monad({
T: FunctionFunctor,
μ: (f) => (x) => f(x)(x),
η: (y) => (x) => y,
});
FunctionMonad.bind((x) => x + 20, (y) => (x) => y * 100 + x)(3);
function State(run) {
this.run = run;
}
var StateFunctor = new Functor((g) => (x) => new State((s) => {
const [y, s1] = x.run(s);
return [g(y), s1];
}));
var StateMonad = new Monad({
T: StateFunctor,
μ: (x) => new State((s) => {
const [y, s1] = x.run(s);
const [z, s2] = y.run(s1);
return [z, s2];
}),
η: (x) => new State((s) => [x, s]),
});
State.prototype.bind = function(k) {
return StateMonad.bind(this, k);
}
var getState = new State((s) => [s, s]);
var setState = (s) => new State((_) => [null, s]);
getState.bind((s) => setState(s * 10).bind((_) => getState)).run(2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment