Skip to content

Instantly share code, notes, and snippets.

@venil7
Last active May 24, 2020 17:37
Show Gist options
  • Save venil7/660aaa44629e996815d817559c8ffd33 to your computer and use it in GitHub Desktop.
Save venil7/660aaa44629e996815d817559c8ffd33 to your computer and use it in GitHub Desktop.
TypeScript State Monad
type StateM<S, T> = {
runState: (state: S) => T,
then: <U>(func: (t: T, pure: <U>(u: U) => StateM<S, U>) => StateM<S, U>) => StateM<S, U>,
};
const stateM = function <S, T>(runState: (state: S) => [S, T]): StateM<S, T> {
return {
runState: function (s: S): T {
const [, t] = runState(s);
return t;
},
then: function <U>(func: (t: T, pure: <U>(u: U) => StateM<S, U>) => StateM<S, U>) {
return stateM<S, U>((s: S) => {
const [sUpd, t] = runState(s);
const pure = function <U>(u: U) { return stateM<S, U>(_ => [sUpd, u]); }
return [sUpd, func(t, pure).runState(sUpd)];
});
},
};
};
const createCounterMonad = (testFunc: ((n: number) => boolean)) => stateM<number[], number>((nums) => {
const newState = [...nums].filter(n => !testFunc(n)); //filter out all that dont test
const countFiltered = nums.length - newState.length; //count number of filtered out;
return [newState, countFiltered];
});
const evenNumbers = createCounterMonad(n => n % 2 === 0);
const div3Numbers = createCounterMonad(n => n % 3 === 0);
const results = evenNumbers // even: X, div: Y
.then((evens, _) => div3Numbers
.then((div3s, pure) => pure<string>(`even: ${evens}, div3: ${div3s}`)))
.runState([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment