Skip to content

Instantly share code, notes, and snippets.

@baetheus
Last active March 1, 2021 05:58
Show Gist options
  • Select an option

  • Save baetheus/b1aa9292de6f5f53fb6c9721b2c692d3 to your computer and use it in GitHub Desktop.

Select an option

Save baetheus/b1aa9292de6f5f53fb6c9721b2c692d3 to your computer and use it in GitHub Desktop.
Combination of pelotom hkts and fpts HKT
// Option
export type None = { tag: "None" };
export type Some<A> = { tag: "Some"; value: A };
export type Option<A> = None | Some<A>;
// Either
export type Left<L> = { tag: "Left"; left: L };
export type Right<R> = { tag: "Right"; right: R };
export type Either<L, R> = Left<L> | Right<R>;
// HKT
export interface Types1<A> {
Option: Option<A>;
}
export interface Types2<A, B> {
Either: Either<A, B>;
}
export type URIS1 = keyof Types1<any>;
export type URIS2 = keyof Types2<any, any>;
export type URIS = URIS1 | URIS2;
export type TypeMap1<URI extends URIS1, A> = Types1<A>[URI];
export type TypeMap2<URI extends URIS2, A, B> = Types2<A, B>[URI];
// Substitution
declare const index: unique symbol;
export interface _<N extends number = 0> {
[index]: N;
}
export type $<URI extends URIS, S extends any[]> = URI extends URIS1
? Types1<S[0]>[URI]
: URI extends URIS2 ? Types2<S[0], S[1]>[URI]
: never;
// Functor
export type FunctorFn<URI> = URI extends URIS1
? <A, B>(fab: (a: A) => B) => (ma: $<URI, [A]>) => $<URI, [B]>
: URI extends URIS2
? <A, B>(fab: (a: A) => B) => <Z>(ma: $<URI, [Z, A]>) => $<URI, [Z, B]>
: never;
const f1: FunctorFn<"Option"> = (fab) =>
(ma) => ma.tag === "None" ? ma : { tag: "Some", value: fab(ma.value) };
// Inferred: <A, B>(fab: (a: A) => B) => (ma: Option<A>) => Option<B>
const f2: FunctorFn<"Either"> = (fab) =>
(ma) => ma.tag === "Left" ? ma : { tag: "Right", right: fab(ma.right) };
// Inferred: <A, B>(fab: (a: A) => B) => <Z>(ma: Either<Z, A>) => Either<Z, B>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment