Skip to content

Instantly share code, notes, and snippets.

@regevbr
Created May 12, 2022 17:09
Show Gist options
  • Save regevbr/9a8c7ebd9d8ece95021496c1111e00a4 to your computer and use it in GitHub Desktop.
Save regevbr/9a8c7ebd9d8ece95021496c1111e00a4 to your computer and use it in GitHub Desktop.
// 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