Skip to content

Instantly share code, notes, and snippets.

@tel
Created May 11, 2015 22:31
Show Gist options
  • Save tel/73ea3adc0e821ba23317 to your computer and use it in GitHub Desktop.
Save tel/73ea3adc0e821ba23317 to your computer and use it in GitHub Desktop.
Maybe for TypeScript
'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