Skip to content

Instantly share code, notes, and snippets.

@nameoverflow
Last active December 23, 2018 06:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nameoverflow/8e0907b01422379d7ce080c8de11818a to your computer and use it in GitHub Desktop.
Save nameoverflow/8e0907b01422379d7ce080c8de11818a to your computer and use it in GitHub Desktop.
Monad-like do-notation in TypeScript
export interface Monad<T> {
mbind<U>(t: (T) => Monad<U>): Monad<U>
mreturn<U>(v: U): Monad<U>
}
abstract class Maybe<T> implements Monad<T> {
abstract mbind<U>(t: (T) => Maybe<U>): Maybe<U>
mreturn<U>(v: U): Maybe<U> {
return new Just(v)
}
}
class Just<T> extends Maybe<T> {
private value: T
constructor(v: T) {
super()
this.value = v
}
mbind<U>(t: (T) => Maybe<U>): Maybe<U> {
return t(this.value)
}
}
class Nothing<T> extends Maybe<T> {
mbind<U>(t: (T) => Maybe<U>): Maybe<U> {
return this
}
}
export default function doM<T>(g: () => IterableIterator<Monad<T>>): Monad<T> {
let m = g()
const run = (v) => {
const res = m.next(v)
if (res.done) {
return res.value
}
return res.value.mbind(run)
}
return run(undefined)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment