Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

higher kinded type in typescript from fp-ts and URI

In fp-ts they have this workaround for higher kinded types:

export interface HKT<URI, A> {
  readonly _URI: URI;
  readonly _A: A;
}

And it can be used like this:

export interface Foldable<F> {
  readonly URI: F;
  reduce: <A, B>(fa: HKT<F, A>, b: B, f: (b: B, a: A) => B) => B;
}

What are the members _URI and what is _A?

like image 496
dagda1 Avatar asked Apr 14 '18 07:04

dagda1


1 Answers

This article written by the author of fp-ts explains very well,in combination with documentation on TypeScript's union types.

_A is the type of the value in our HKT: HKT<"Option", string> => Option<string>. We'll see how mapping works in a bit.

_URI is the identifier for the HKT, for example Option.ts. It has 2 instances, None and Some, both of which have "Option" as their _URI.

Taking a look at the usage of F in Foldable we can see it's used in the Type type, along with A; Type<F, A>. Assume F == "Option" & A == string so Type<F, A> == Type<"Option", string>, which is very similar to Option<string>. Currently, we cannot pass a generic type to another generic as it's generic parameter: <F,A>(fa: F<A>) will not compile and this is the main problem.

To achieve Type<"Option", string> => Option<string>, there are several "mapping" interfaces (this is explained in the article). We can see this done for Option here:

declare module './HKT' {
  interface URI2HKT<A> {
    Option: Option<A>
  }
}

The leftmost Option is a string key, the rightmost is the actual Option type, this is a normal record interface after all. Let's have a quick look at the definition of Type: type Type<URI extends URIS, A> = URI2HKT<A>[URI].

URI2HKIT is a map from our "Option" to our actual Option. It's allowing is to pass 2 generic parameters to get back our value type wrapped in our higher kinded type, solving the generics issue mentioned earlier.

like image 122
MaxWillmott Avatar answered Oct 21 '22 00:10

MaxWillmott