-
-
Save alilosoft/a6ae0d1f17a3da5dde4bcac9fd2e619a to your computer and use it in GitHub Desktop.
Algebraic Data Types in 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
// Types: | |
type Just<T> = { Just: T } | |
type Nothing = {} | |
type Maybe<T> = Just<T> | Nothing | |
type Left<L> = { Left: L } | |
type Right<R> = { Right: R } | |
type Either<L, R> = Left<L> | Right<R> | |
// For convenience: | |
const Nothing: Nothing = {}; | |
function Just<T>(x: T): Just<T> { | |
return { Just: x }; | |
} | |
function Left<L>(x: L): Left<L> { | |
return { Left: x }; | |
} | |
function Right<R>(x: R): Right<R> { | |
return { Right: x }; | |
} | |
// Type guards: | |
function isJust<T>(x: Maybe<T>): x is Just<T> { | |
return "Just" in x; | |
} | |
function isLeft<L, R>(x: Either<L, R>): x is Left<L> { | |
return "Left" in x; | |
} | |
function isRight<L, R>(x: Either<L, R>): x is Right<R> { | |
return "Right" in x; | |
} | |
// Extraction functions: | |
function fromMaybe<T>(fallback: T, x: Maybe<T>): T { | |
return isJust(x) ? x.Just : fallback; | |
} | |
function fromEither<L, R, Y>(fl: (l: L) => Y, fr: (r: R) => Y, x: Either<L, R>): Y { | |
return isLeft(x) ? fl(x.Left) : fr(x.Right); | |
} | |
// Example values: | |
const aJust: Maybe<number> = Just(5); | |
const aNothing: Maybe<number> = Nothing; | |
const aLeft: Either<string, number> = Left("error"); | |
const aRight: Either<string, number> = Right(100); | |
// Using the extraction functions: | |
const id = <T>(x: T) => x; | |
console.log(fromMaybe(0, aJust)); // 5 | |
console.log(fromMaybe(0, aNothing)); // 0 | |
console.log(fromEither(_ => 0, id, aLeft)); // 0 | |
console.log(fromEither(_ => 0, id, aRight)); // 100 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment