Skip to content

Instantly share code, notes, and snippets.

@tonyonodi
Created June 17, 2019 23:34
Show Gist options
  • Save tonyonodi/4f93df367dde0c7548cc8469dbcf8954 to your computer and use it in GitHub Desktop.
Save tonyonodi/4f93df367dde0c7548cc8469dbcf8954 to your computer and use it in GitHub Desktop.
A more class based functor implementation
// Maybe
class Nothing {
readonly tag: "None" = "None";
public map = (): Nothing => new Nothing();
}
class Just<A> {
readonly tag: "Just" = "Just";
constructor(readonly value: A) {}
public map = <B>(fn: (a: A) => B): Just<B> => new Just(fn(this.value));
}
type Maybe<A> = Just<A> | Nothing;
const just = <A>(val: A): Maybe<A> => new Just(val);
const nothing: Maybe<never> = new Nothing();
// List
class List<A> {
readonly tag: "List" = "List";
constructor(readonly value: A[]) {}
public map = <B>(fn: (a: A) => B): List<B> => new List(this.value.map(fn));
}
const list = <A>(arr: A[]) => new List(arr);
// Functor
type Functor<A> = List<A> | Maybe<A>;
function map<A, B>(fn: (x: A) => B, m: List<A>): List<B>;
function map<A, B>(fn: (x: A) => B, m: Nothing): Nothing;
function map<A, B>(fn: (x: A) => B, m: Maybe<A>): Maybe<B>;
function map<A, B>(fn: (x: A) => B, m: Functor<A>) {
return (m as { map: (fn: (a: A) => B) => Functor<B> }).map(fn);
}
// Test code
const double = (n: number) => n * 2;
const n = map(double, nothing); // Nothing
const l1 = list([1, 2, 3, 5]);
const l2 = map(double, l1); // List<number>
const mapDoubleM = (m: Maybe<number>) => {
return map(double, m);
};
const doubled = mapDoubleM(just(5)); // Maybe<number>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment