-
-
Save joshburgess/9bb3ea4e9e1ea81de2d12cee1b43e64d to your computer and use it in GitHub Desktop.
HKTs in Flow
This file contains hidden or 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
| // @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