Created
May 11, 2015 22:31
-
-
Save tel/73ea3adc0e821ba23317 to your computer and use it in GitHub Desktop.
Maybe for TypeScript
This file contains hidden or 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
'use strict'; | |
export interface Tuple<A, B> { | |
fst: A; | |
snd: B; | |
} | |
export module Tuple { | |
export function of<A, B>(a: A, b: B): Tuple<A, B> { | |
return {fst: a, snd: b}; | |
} | |
} | |
export class Maybe<A> { | |
fold<R>(match: { just: (a: A) => R, nothing: R }): R; | |
map<B>(fn: (a: A) => B): Maybe<B> { return Maybe.map(fn)(this); }; | |
zip<B>(mb: Maybe<B>): Maybe<Tuple<A, B>> { return Maybe.zip(this, mb); }; | |
zipWith<B, R>(mb: Maybe<B>, fn: (a: A, b: B) => R): Maybe<R> { return Maybe.zipWith(fn)(this, mb); }; | |
bind<B>(fn: (a: A) => Maybe<B>): Maybe<B> { return Maybe.bind(fn)(this); }; | |
or(m: Maybe<A>): Maybe<A> { return Maybe.or(this, m); }; | |
guard(b: boolean): Maybe<{}> { if (b) { return Maybe.of({}) } else { return Maybe.zero() } }; | |
orElse(def: A): A { | |
return this.fold({ | |
just: (a) => { return a; }, | |
nothing: def | |
}) | |
} | |
} | |
export module Maybe { | |
export class Just<A> extends Maybe<A> { | |
constructor(public value: A) { super(); }; | |
fold<R>(match) { return match.just(this.value); } | |
} | |
export class Nothing<A> extends Maybe<A> { | |
constructor() { super(); }; | |
fold<R>(match) { return match.nothing; } | |
} | |
export function of<A>(value: A): Maybe<A> { | |
return new Just(value); | |
} | |
export function zero<A>(): Nothing<A> { | |
return new Nothing(); | |
} | |
export function map<A, B>(fn: (a: A) => B): (m: Maybe<A>) => Maybe<B> { | |
return function morphism(ma) { | |
return ma.fold({ | |
just: (a) => { return new Just(fn(a)) }, | |
nothing: zero() | |
}); | |
} | |
} | |
export function bind<A, B>(fn: (a: A) => Maybe<B>): (m: Maybe<A>) => Maybe<B> { | |
return function morphism(ma) { | |
return ma.fold({ | |
just: (a) => { return fn(a) }, | |
nothing: zero() | |
}) | |
} | |
} | |
export function zipWith<A, B, R>(fn: (A, B) => R): ((ma: Maybe<A>, mb: Maybe<B>) => Maybe<R>) { | |
return function(ma, mb) { | |
return ma.fold({ | |
just: (a) => { return mb.fold({ | |
just: (b) => { return of(fn(a,b)); }, | |
nothing: zero() | |
})}, | |
nothing: zero() | |
}) | |
} | |
} | |
export function zip<A, B>(ma: Maybe<A>, mb: Maybe<B>): Maybe<Tuple<A, B>> { | |
return zipWith(Tuple.of)(ma, mb); | |
} | |
export function ap<A, B>(mf: Maybe<(a: A) => B>, ma: Maybe<A>): Maybe<B> { | |
return mf.fold({ | |
just: (f) => { return ma.fold({ | |
just: (a) => { return of(f(a)); }, | |
nothing: zero() | |
})}, | |
nothing: zero() | |
}) | |
} | |
export function or<A>(m1: Maybe<A>, m2: Maybe<A>): Maybe<A> { | |
return m1.fold({ | |
just: (_) => { return m1; }, | |
nothing: m2 | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment