Skip to content

Instantly share code, notes, and snippets.

@trknhr
Created December 25, 2016 14:34
Show Gist options
  • Save trknhr/238107a1bbb22a1f5d27a095135136e6 to your computer and use it in GitHub Desktop.
Save trknhr/238107a1bbb22a1f5d27a095135136e6 to your computer and use it in GitHub Desktop.
export class StateTuple<A, S>{
a: A
s: S
}
export class State<S, A>{
run = null;
constructor(run: (S) => StateTuple<A, S>){
this.run = run;
}
map = <B>(f: (A)=> B): State<S,B> =>
this.flatMap(a => State.unit(f(a)))
map2 = <B,C>(sb: State<S,B>) => (f: (A, B) => C): State<S,C> =>
this.flatMap(a => sb.map(b => f(a,b)))
flatMap = <B>(f: (A) => State<S,B>): State<S,B> =>
new State(s => {
const r = this.run(s)
return f(r.a).run(r.s)
})
static unit = <S,A>(a: A): State<S, A> =>
new State(s => ({a, s}))
static sequence = <S,A>(sas: State<S,A>[]): State<S, A[]> => {
const go = (s: S, actions: State<S,A>[], acc: A[]): {list: A[], s: S} => {
switch (actions.length){
case 0:
return {list: acc, s: s}
default:
const state = actions[0].run(s)
return go(state.s, actions.slice(1), acc.concat([state.a]))
}
}
return new State(s => {
const r = go(s, sas, [])
return {a: r.list, s: r.s}
})
}
static modify = <S>(f: (S) => S): State<S, void> => {
return State.get().flatMap(s => {
return State.set(f(s))
}
)
}
static get = <S>(): State<S,S> =>
new State(s => {
return {a: s, s}
})
static set = <S>(s: S): State<S, void> =>
new State(_ => ({a: () => {}, s}))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment