Skip to content

Instantly share code, notes, and snippets.

@ulve
Created October 23, 2017 10:40
Show Gist options
  • Save ulve/000971b20c6d8c9524ab04aa2ff1430e to your computer and use it in GitHub Desktop.
Save ulve/000971b20c6d8c9524ab04aa2ff1430e to your computer and use it in GitHub Desktop.
StateMonad in TypeScript
class State {
private constructor(protected state) {}
Map = f =>
new State(s => {
var prev = this.state(s);
return { value: f(prev.value), state: prev.state };
});
Join = () =>
new State(s => {
var prev = this.state(s);
var inner = prev.value.state(prev.state);
return inner;
});
Bind = f => this.Map(f).Join();
EvalState = i => this.state(i).value;
ExecState = i => this.state(i).state;
static Get = () => new State(s => ({ value: s, state: s }));
static Put = ns => new State(s => ({ value: undefined, state: ns }));
static Modify = f => State.Get().Bind(s => State.Put(f(s)));
static Gets = f => State.Get().Bind(s => State.Pure(f(s)));
static Pure = v => new State(s => ({ value: v, state: s }));
}
function randVal() {
return Math.floor(Math.random() * 1000 - 500);
}
const a = randVal();
const b = randVal();
const c = randVal();
const f = x => State.Pure(x + b);
const g = x => State.Pure(x + c);
const m = State.Pure(a);
console.log(
`Left identity: ${State.Pure(a)
.Bind(f)
.EvalState(0) === f(a).EvalState(0)}`
);
console.log(
`Right identity ${m.Bind(State.Pure).EvalState(0) === m.EvalState(0)}`
);
console.log(
`Associativity ${m
.Bind(f)
.Bind(g)
.EvalState(0) === m.Bind(x => f(x).Bind(g)).EvalState(0)}`
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment