Skip to content

Instantly share code, notes, and snippets.

@ivan-demchenko
Last active March 28, 2017 07:27
Show Gist options
  • Save ivan-demchenko/ce78c0235ae1fe07b49b87b9d2bbb945 to your computer and use it in GitHub Desktop.
Save ivan-demchenko/ce78c0235ae1fe07b49b87b9d2bbb945 to your computer and use it in GitHub Desktop.
This is my experiment to implement a functor type class using TypeScript
interface Functor<A> {
fmap<B>(f: (x: A) => B): Functor<B>
}
const fmap = <A, B>(f: (x: A) => B) => (fa: Functor<A>): Functor<B> => fa.fmap(f);
//=== String
interface String extends Functor<String> {
}
// Instance Functor String
String.prototype.fmap = function <B>(fn: (x: String) => B) {
return fn(this);
};
//=== Array A
interface Array<T> extends Functor<T> {
}
// Instance Functor Array
Array.prototype.fmap = Array.prototype.map;
//=== Maybe A
interface Maybe<A> extends Functor<A> {
outOfMaybe: () => A | null;
}
interface INothing<A> extends Maybe<A> {
}
interface IJust<A> extends Maybe<A> {
val: A
}
class Nothing<A> implements INothing<A> {
/// Instance Functor Maybe
fmap() {
return new Nothing()
}
outOfMaybe() {
return null;
}
}
class Just<A> implements IJust<A> {
constructor(public val: A) { }
/// Instance Functor Maybe
fmap<B>(f: (x: A) => B) {
return new Just(f(this.val))
}
outOfMaybe() {
return this.val;
}
}
const justArr = new Just([1, 2, 3]);
const concat = <A>(a: A) => (xs: A[]) => xs.concat(a);
const inc = (x: number) => x + 1;
interface Comp {
<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C
}
const comp: Comp = (f) => (g) => (x) => g(f(x))
// (fmap . fmap) inc (Just [1, 2])
const x1 = comp(fmap)(fmap)(inc)(justArr);
// fmap(fmap(+10) . (++ [3])) $ Just [1,2]
const x2 = fmap(comp(fmap(inc), concat(4)))(justArr);
// fmap(fmap(+10)) $ fmap (++ [3]) $ Just [1,2]
const x3 = fmap(fmap(inc))(fmap(concat(4))(justArr));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment