I am trying to make a state monad in typescript, the implementation is roughly like this:
export class State<S, A> implements PromiseLike<A> {
readonly [Symbol.toStringTag] = "StateMoand";
runState: RunState<S, A>;
...
constructor(runState: RunState<S, A>) {
this.runState = runState;
...
}
static pure<S, A>(a: A): State<S, A> {
return new State<S, A>(s => [a, s]);
}
bind<B>(f: (a: A) => State<S, B>) {
const runState: RunState<S, B> = (s: S) => {
const [a, s1] = this.runState(s);
return f(a).runState(s1);
}
return new State(runState);
}
then = this.bind;
...
}
This implementation works fine if I only use method chaining, but I also want to use aysnc/await syntax to simulate the do notation in Haskell. What I want to achieve is this:
it("then", async () => {
const state = new State<string, number>(s => {
return [Number.parseInt(s), s + "0"];
});
const f = async (state: State<string, number>) => {
const p = await state.get();
await state.put("11");
await state.modify(s => s + "22");
return p;
}
await f(state);
}
I want f to return a State<S, A>, but that requires me to overload return somehow. Is there any way I can achieve the effect?