Skip to content

Instantly share code, notes, and snippets.

@leihuang23
Created January 2, 2019 01:00
Show Gist options
  • Save leihuang23/2c3e02bda8942c2e422d11bddb396450 to your computer and use it in GitHub Desktop.
Save leihuang23/2c3e02bda8942c2e422d11bddb396450 to your computer and use it in GitHub Desktop.
State monad in JS
const composeK = (...fns) =>
fns.reduce((f, g) => (...args) => g(...args).chain(f));
const liftA2 = (f, m1, m2) => m1.map(f).ap(m2);
const K = a => b => a;
const State = computation => {
const map = f =>
State(state => {
const prev = computation(state);
return { value: f(prev.value), state: prev.state };
});
const ap = other =>
State(state => {
const prev = computation(state);
const fn = prev.value;
return other.map(fn).runWith(prev.state);
});
const chain = fn =>
State(state => {
const prev = computation(state);
const next = fn(prev.value);
return next.runWith(prev.state);
});
const runWith = computation;
const evalWith = initState => computation(initState).value;
const execWith = initState => computation(initState).state;
return Object.freeze({
map,
ap,
chain,
evalWith,
runWith,
execWith
});
};
const modify = f => State(state => ({ value: undefined, state: f(state) }));
State.get = (f = x => x) => State(state => ({ value: f(state), state }));
State.modify = modify;
State.put = state => modify(K(state));
State.of = value => State(state => ({ value, state }));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment