Created
July 31, 2018 18:03
-
-
Save gigobyte/47b682a6d33d5b77d8724a1d87ff5181 to your computer and use it in GitHub Desktop.
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
interface ADTKind<T> { | |
kind: T | |
} | |
type ADT1<Name, T> = (...args: [T]) => ADTContainer1<Name, T> | |
type ADT2<Name, T, T2> = (...args: [T, T2]) => ADTContainer2<Name, T, T2> | |
type ADT3<Name, T, T2, T3> = (...args: [T, T2, T3]) => ADTContainer3<Name, T, T2, T3> | |
class ADTContainer1<Name, T> implements ADTKind<Name> { | |
kind: Name = null as any as Name | |
0: T | |
length: 1 = 1 | |
constructor(private args: [T]) {} | |
*[Symbol.iterator]() { | |
yield this.args[0] | |
} | |
} | |
class ADTContainer2<Name, T, T2> implements ADTKind<Name> { | |
kind: Name = null as any as Name | |
0: T | |
1: T2 | |
length: 2 = 2 | |
constructor(private args: [T, T2]) {} | |
*[Symbol.iterator]() { | |
yield this.args[0] | |
yield this.args[1] | |
} | |
} | |
class ADTContainer3<Name, T, T2, T3> implements ADTKind<Name> { | |
kind: Name = null as any as Name | |
0: T | |
1: T2 | |
2: T3 | |
length: 3 = 3 | |
constructor(private args: [T, T2, T3]) {} | |
*[Symbol.iterator]() { | |
yield this.args[0] | |
yield this.args[1] | |
yield this.args[2] | |
} | |
} | |
function ADT<Name, T>(): ADT1<Name, T> | |
function ADT<Name, T, T2>(): ADT2<Name, T, T2> | |
function ADT<Name, T, T2, T3>(): ADT3<Name, T, T2, T3> | |
function ADT<Name, T, T2, T3, T4>(): any { | |
return (...args: [T, T2, T3]) => { | |
if (args.length === 3) { | |
return new ADTContainer3<Name, T, T2, T3>(args) | |
} else if (args.length === 2) { | |
return new ADTContainer2<Name, T, T2>(args as any as [T, T2]) | |
} else if (args.length === 1){ | |
return new ADTContainer1<Name, T>(args as any as [T]) | |
} | |
return {} | |
} | |
} | |
const Point = ADT<'Point', number, string>() | |
const Square = ADT<'Square', number>() | |
type Shape | |
= ReturnType<typeof Point> | |
| ReturnType<typeof Square> | |
const a: Shape = Point(1, 'ad') as Shape | |
type ExtractPatterns<T extends ADTKind<any>, U> = | |
{ [k in T['kind']]: (value: () => U) => void } | |
const caseOf = <T extends ADTContainer3<any, any, any, any>, U>(adt: T, patterns: ExtractPatterns<T, U>) => {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment