Last active
June 16, 2020 11:54
-
-
Save afcastano/dd94b85bc65519eb55784ac1cec45839 to your computer and use it in GitHub Desktop.
Typescript IO monad with Promises
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class IO<A>{ | |
private effect: Effect<A> | |
constructor(effect: Effect<A>) { | |
this.effect = effect | |
} | |
static of<T>(val: T) { | |
return new IO(() => Promise.resolve(val)) | |
} | |
map<B>(f: (val: A) => B): IO<B> { | |
const mappedEffect: Effect<B> = async (effects: Effects) => { | |
const unwrappedVal: A = await this.effect(effects); | |
return f(unwrappedVal); | |
}; | |
return new IO(mappedEffect); | |
} | |
flatMap<B>(f: (val: A) => IO<B>): IO<B> { | |
const boundEffect: Effect<B> = async (effects: Effects) => { | |
const unwrappedVal: A = await this.effect(effects); | |
const mappedIO: IO<B> = f(unwrappedVal); | |
return mappedIO.effect(effects); | |
} | |
return new IO(boundEffect); | |
} | |
eval(effects: Effects): Promise<A> { | |
return this.effect(effects) | |
} | |
} | |
export const _do = (fn: (...args: any[]) => Generator<IO<any>, any, any>) => (...args: any[]) => { | |
const gen = fn(...args); | |
const next = (val?: any) => { | |
const res: any = gen.next(val); | |
if(!res.done) return res.value.flatMap(next); | |
if(res.value && res.value.effect) return res.value; | |
return IO.of(res.value); | |
} | |
return next(); | |
} | |
export type Effect<T> = (effects: Effects) => Promise<T> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment