Created
May 12, 2022 17:09
-
-
Save regevbr/9a8c7ebd9d8ece95021496c1111e00a4 to your computer and use it in GitHub Desktop.
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
// tslint:disable:no-empty-interface | |
// Library | |
// (Based in part on https://bitbucket.org/espalier-spreadsheet/espalier/src/b9fef3fd739d42cacd479e50f20cb4ab7078d534/src/lib/type-funcs.ts?at=master&fileviewer=file-view-default#type-funcs.ts-23 | |
// with inspiration from https://github.com/gcanti/fp-ts/blob/master/HKT.md) | |
// https://stackoverflow.com/questions/51815782/typescript-array-of-different-generic-types/51816182#51816182 | |
interface ExistentialType<URI> { | |
readonly _URI: URI | |
} | |
interface URItoKind<A> { | |
} | |
interface URItoKind2<E, A> { | |
} | |
interface URItoKind3<R, E, A> { | |
} | |
interface URItoKind4<S, R, E, A> { | |
} | |
type URIS = keyof URItoKind<any> | |
type URIS2 = keyof URItoKind2<any, any> | |
type URIS3 = keyof URItoKind3<any, any, any> | |
type URIS4 = keyof URItoKind4<any, any, any, any> | |
type Kind<URI extends URIS, A> = URI extends URIS ? URItoKind<A>[URI] : never | |
type Kind2<URI extends URIS2, E, A> = URI extends URIS2 ? URItoKind2<E, A>[URI] : never | |
type Kind3<URI extends URIS3, R, E, A> = URI extends URIS3 ? URItoKind3<R, E, A>[URI] : never | |
type Kind4<URI extends URIS4, S, R, E, A> = URI extends URIS4 ? URItoKind4<S, R, E, A>[URI] : never | |
function makeExistential<URI extends URIS4, S, R, E, A> | |
(val: Kind4<URI, S, R, E, A>): ExistentialType<URI>; | |
function makeExistential<URI extends URIS3, R, E, A> | |
(val: Kind3<URI, R, E, A>): ExistentialType<URI>; | |
function makeExistential<URI extends URIS2, E, A> | |
(val: Kind2<URI, E, A>): ExistentialType<URI>; | |
function makeExistential<URI extends URIS, A> | |
(val: Kind<URI, A>): ExistentialType<URI>; | |
function makeExistential<URI>(value: any): ExistentialType<URI> { | |
return value; | |
} | |
function enterExistential<URI extends URIS4, Return>(existentialValue: ExistentialType<URI>, | |
cb: | |
<S, R, E, A> | |
(value: Kind4<URI, S, R, | |
E, A>) => Return): Return; | |
function enterExistential<URI extends URIS3, Return>(existentialValue: ExistentialType<URI>, | |
cb: | |
<R, E, A> | |
(value: Kind3<URI, R, | |
E, A>) => Return): Return; | |
function enterExistential<URI extends URIS2, Return>(existentialValue: ExistentialType<URI>, | |
cb: | |
<E, A> | |
(value: Kind2<URI, | |
E, A>) => Return): Return; | |
function enterExistential<URI extends URIS, Return>(existentialValue: ExistentialType<URI>, | |
cb: | |
<A> | |
(value: Kind<URI, A>) => Return): Return; | |
function enterExistential<Return>(existentialValue: any, cb: (value: any) => Return): Return { | |
return cb(existentialValue); | |
} | |
// tslint:disable-next-line:variable-name | |
const F_4 = Symbol(); | |
// tslint:disable-next-line:variable-name | |
const F_3 = Symbol(); | |
// tslint:disable-next-line:variable-name | |
const F_2 = Symbol(); | |
// tslint:disable-next-line:variable-name | |
const F_1 = Symbol(); | |
interface URItoKind4<S, R, E, A> { | |
[F_4]: { | |
a1: S, a2: R, a3: E, a4: A | |
fn: (a1: S, a2: R, a3: E, a4: A) => string | |
}; | |
} | |
interface URItoKind3<R, E, A> { | |
[F_3]: { | |
a1: R, a2: E, a3: A | |
fn: (a1: R, a2: E, a3: A) => string | |
}; | |
} | |
interface URItoKind2<E, A> { | |
[F_2]: { | |
a1: E, a2: A | |
fn: (a1: E, a2: A) => string | |
}; | |
} | |
interface URItoKind<A> { | |
[F_1]: { | |
a1: A | |
fn: (a1: A) => string | |
}; | |
} | |
type F_4 = typeof F_4; | |
type F_3 = typeof F_3; | |
type F_2 = typeof F_2; | |
type F_1 = typeof F_1; | |
const f4Arr: ExistentialType<F_4>[] = []; | |
const f3Arr: ExistentialType<F_3>[] = []; | |
const f2Arr: ExistentialType<F_2>[] = []; | |
const f1Arr: ExistentialType<F_1>[] = []; | |
f3Arr.push(makeExistential<F_3, number, boolean, string>({ | |
a1: 5, | |
a2: false, | |
a3: '5', | |
fn: (a1: number, a2: boolean, a3: string) => a1.toString() + String(a2), | |
})); | |
f3Arr.push(makeExistential<F_3, number, string, boolean>({ | |
a1: 5, | |
a2: 'f', | |
a3: true, | |
fn: (a1: number, a2: string, a3: boolean) => String(a1 && a2 && a3), | |
})); | |
for (const el of f3Arr) { | |
enterExistential(el, (val) => | |
console.log(val.fn(val.a1, val.a2, val.a3))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment