Skip to content

Instantly share code, notes, and snippets.

@jbrownson
Created January 5, 2016 18:14
Show Gist options
  • Select an option

  • Save jbrownson/2e9eebe0446a36c62a94 to your computer and use it in GitHub Desktop.

Select an option

Save jbrownson/2e9eebe0446a36c62a94 to your computer and use it in GitHub Desktop.
ADTs in Javascript using functions
export type Disjunction<T, U> = <Z>(a: (t: T) => Z, b: (u: U) => Z) => Z
export type Disjunction3<T, U, V> = Disjunction<T, Disjunction<U, V>>
export type Disjunction4<T, U, V, W> = Disjunction3<T, U, Disjunction<V, W>>
export type List<T> = Disjunction<{head: T, tail: List<T>}, {}>
export type Maybe<T> = Disjunction<T, {}>
export function listFromArray<T>(array: T[]): List<T> {
return <Z>(a: (x: {head: T, tail: List<T>}) => Z, b: () => Z) =>
array.length == 0
? b()
: a({head: array[0], tail: listFromArray(array.slice(1))}) }
export const emptyList = <T, Z>(a: (x: {head: T, tail: List<T>}) => Z, b: () => Z) => b()
export function prepend<T>(t: T, list: List<T>): List<T> {
return <Z>(a: (x: {head: T, tail: List<T>}) => Z, b: () => Z) => a({head: t, tail: list}) }
export function any<T>(predicate: (t: T) => boolean, list: List<T>): boolean {
return list(({head, tail}) => predicate(head) || any(predicate, tail), () => false) }
export function arrayFromList<T>(list: List<T>): T[] {
return _arrayFromList(list, emptyList) }
function _arrayFromList<T>(list: List<T>, seen: List<List<T>>): T[] {
return list(
({head, tail}) => any(t => t === list, seen)
? []
: [head].concat(_arrayFromList(tail, prepend(list, seen))),
() => []) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment