Created
June 17, 2019 23:34
-
-
Save tonyonodi/4f93df367dde0c7548cc8469dbcf8954 to your computer and use it in GitHub Desktop.
A more class based functor implementation
This file contains 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
// 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