|
export interface Functor<F> { |
|
readonly URI: F |
|
readonly map: <A, B>(fa: HKT<F, A>, f: (a: A) => B) => HKT<F, B> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface Functor1<F extends URIS> { |
|
readonly URI: F |
|
readonly map: <A, B>(fa: Kind<F, A>, f: (a: A) => B) => Kind<F, B> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface Functor2<F extends URIS2> { |
|
readonly URI: F |
|
readonly map: <E, A, B>(fa: Kind2<F, E, A>, f: (a: A) => B) => Kind2<F, E, B> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface Functor2C<F extends URIS2, E> { |
|
readonly URI: F |
|
readonly _E: E |
|
readonly map: <A, B>(fa: Kind2<F, E, A>, f: (a: A) => B) => Kind2<F, E, B> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface Functor3<F extends URIS3> { |
|
readonly URI: F |
|
readonly map: <R, E, A, B>(fa: Kind3<F, R, E, A>, f: (a: A) => B) => Kind3<F, R, E, B> |
|
} |
|
|
|
/** |
|
* @since 2.2.0 |
|
*/ |
|
export interface Functor3C<F extends URIS3, E> { |
|
readonly URI: F |
|
readonly _E: E |
|
readonly map: <R, A, B>(fa: Kind3<F, R, E, A>, f: (a: A) => B) => Kind3<F, R, E, B> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface Functor4<F extends URIS4> { |
|
readonly URI: F |
|
readonly map: <S, R, E, A, B>(fa: Kind4<F, S, R, E, A>, f: (a: A) => B) => Kind4<F, S, R, E, B> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorComposition<F, G> { |
|
readonly map: <A, B>(fa: HKT<F, HKT<G, A>>, f: (a: A) => B) => HKT<F, HKT<G, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorCompositionHKT1<F, G extends URIS> { |
|
readonly map: <A, B>(fa: HKT<F, Kind<G, A>>, f: (a: A) => B) => HKT<F, Kind<G, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorCompositionHKT2<F, G extends URIS2> { |
|
readonly map: <E, A, B>(fa: HKT<F, Kind2<G, E, A>>, f: (a: A) => B) => HKT<F, Kind2<G, E, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorCompositionHKT2C<F, G extends URIS2, E> { |
|
readonly map: <A, B>(fa: HKT<F, Kind2<G, E, A>>, f: (a: A) => B) => HKT<F, Kind2<G, E, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorComposition11<F extends URIS, G extends URIS> { |
|
readonly map: <A, B>(fa: Kind<F, Kind<G, A>>, f: (a: A) => B) => Kind<F, Kind<G, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorComposition12<F extends URIS, G extends URIS2> { |
|
readonly map: <E, A, B>(fa: Kind<F, Kind2<G, E, A>>, f: (a: A) => B) => Kind<F, Kind2<G, E, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorComposition12C<F extends URIS, G extends URIS2, E> { |
|
readonly map: <A, B>(fa: Kind<F, Kind2<G, E, A>>, f: (a: A) => B) => Kind<F, Kind2<G, E, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorComposition21<F extends URIS2, G extends URIS> { |
|
readonly map: <E, A, B>(fa: Kind2<F, E, Kind<G, A>>, f: (a: A) => B) => Kind2<F, E, Kind<G, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorComposition2C1<F extends URIS2, G extends URIS, E> { |
|
readonly map: <A, B>(fa: Kind2<F, E, Kind<G, A>>, f: (a: A) => B) => Kind2<F, E, Kind<G, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorComposition22<F extends URIS2, G extends URIS2> { |
|
readonly map: <FE, GE, A, B>(fa: Kind2<F, FE, Kind2<G, GE, A>>, f: (a: A) => B) => Kind2<F, FE, Kind2<G, GE, B>> |
|
} |
|
|
|
/** |
|
* @since 2.0.0 |
|
*/ |
|
export interface FunctorComposition22C<F extends URIS2, G extends URIS2, E> { |
|
readonly map: <FE, A, B>(fa: Kind2<F, FE, Kind2<G, E, A>>, f: (a: A) => B) => Kind2<F, FE, Kind2<G, E, B>> |
|
} |
|
|
|
/** |
|
* @since 2.2.0 |
|
*/ |
|
export interface FunctorComposition23<F extends URIS2, G extends URIS3> { |
|
readonly map: <FE, R, E, A, B>(fa: Kind2<F, FE, Kind3<G, R, E, A>>, f: (a: A) => B) => Kind2<F, FE, Kind3<G, R, E, B>> |
|
} |
|
|
|
/** |
|
* @since 2.2.0 |
|
*/ |
|
export interface FunctorComposition23C<F extends URIS2, G extends URIS3, E> { |
|
readonly map: <FE, R, A, B>(fa: Kind2<F, FE, Kind3<G, R, E, A>>, f: (a: A) => B) => Kind2<F, FE, Kind3<G, R, E, B>> |
|
} |
🚀 Feature request
Current Behavior
Currently, we're using declaration merging and type level defunctionalization to simulate HKTs.
They did their job well, but there was fundamental problem.
They're too verbose to use!
When we define some data type that's constructor is HKT, we need to define
URIfor it and extend properURItoKindinterface by declaration merging. this is not only boring work but also producing unreadable code.fp-ts/src/Option.ts
Lines 51 to 65 in e708323
This is not only problem about data types, but also type classes.
Actually, It's even worse in case of type classes.
fp-ts/src/Functor.ts
Lines 19 to 163 in e708323
Why those things happens?
Well, IMHO, I think this problem has been caused from two property of current way of encoding HKTs.
So we must write definition for all HKTs separately, by using something like function overloading(which makes code long, and verbose), instead of writing definition at once.
fp-ts/src/StateT.ts
Lines 164 to 185 in e708323
Fundamental idea of current way of simulating HKTs is to express direct reference to HKTs by indirect reference(by using
URI&URItoKind). As well as we choose to go around, it's natural to be suffered from boilerplate codes.Desired Behavior
What I want is simpler & easier & readable encoding of HKTs.
And to break down current limitation of this way of encoding HKTs(ex: It's hard to write HKTs that takes HKTs)
This will make this library more practical.
Suggested Solution
I've found some interesting trick that could be used to encoding HKTs,
How about using this trick to encoding HKTs?
Indeed we need more research and investigations about this(ex: is this safe to use?, is there any limitation?, is there better way of using this trick? what else this trick can do?) but I think discussing about this would be valuable.
Who does this impact? Who is this for?
All of fp-ts users.
Additional context