Skip to content

Instantly share code, notes, and snippets.

@gigobyte
Created July 31, 2018 18:03
Show Gist options
  • Save gigobyte/47b682a6d33d5b77d8724a1d87ff5181 to your computer and use it in GitHub Desktop.
Save gigobyte/47b682a6d33d5b77d8724a1d87ff5181 to your computer and use it in GitHub Desktop.
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