Skip to content

Instantly share code, notes, and snippets.

@gcanti
Last active October 27, 2018 06:56
Show Gist options
  • Save gcanti/b7c1f86e1fac08fc45921160e135a672 to your computer and use it in GitHub Desktop.
Save gcanti/b7c1f86e1fac08fc45921160e135a672 to your computer and use it in GitHub Desktop.
HKTs in Flow
// @flow
// type-level dictionary URI -> type constructor
export type URI2HKT<U, L, A> = {
Identity: Identity<A>
// other type constructors here...
// Option: Option<A>,
// Either: Either<L, A>,
// Foo: Foo<U, L, A>
}
// helper
export type HKT<F, U, L, A> = $ElementType<URI2HKT<U, L, A>, F>
// Functor is defined via HKT
export interface Functor<F> {
URI: F,
map<A, B, U, L>(f: (a: A) => B, fa: HKT<F, U, L, A>): HKT<F, U, L, B>
}
// a function which abstracts over Functor
export function lift<F, A, B, U, L>(F_: Functor<F>): (f: (a: A) => B) => (fa: HKT<F, U, L, A>) => HKT<F, U, L, B> {
return f => fa => F_.map(f, fa)
}
export class Identity<A> {
+value: A
constructor(value: A) {
this.value = value
}
map<B>(f: (a: A) => B): Identity<B> {
return new Identity(f(this.value))
}
}
export const map = <A, B>(f: (a: A) => B, fa: Identity<A>): Identity<B> => {
return fa.map(f)
}
// Functor instance for Identity
export const identity: Functor<'Identity'> = {
URI: 'Identity',
map
}
// let's lift double to the Identity functor
const double = (n: number): number => n * 2
const liftedIdentityDouble = lift(identity)(double)
const y1: number = liftedIdentityDouble(new Identity(1))
/*
39: const y1: number = liftedIdentityDouble(new Identity(1))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Identity. This type is incompatible with
39: const y1: number = liftedIdentityDouble(new Identity(1))
^^^^^^ number
*/
const y2: Identity<number> = liftedIdentityDouble(new Identity(1))
// ok
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment