3 ms·
Say you'd like to have an interface for things that are 'mappable'. For example, for arrays we could write: interface Mappable<Array> { map<A, B>(f:
by zcesur 6y ago
Say you'd like to have an interface for things that are 'mappable'. For example, for arrays we could write:
interface Mappable<Array> {
map<A, B>(f: (a: A) => B, fa: Array<A>): Array<B>
}
Likewise, for `Promise`s we could write:
interface Mappable<Promise> {
map<A, B>(f: (a: A) => B, fa: Promise<A>): Promise<B>
}
But in order to generalize this interface to an arbitrary type constructor such that `F: * -> *`, we would need to write
interface Mappable<F> {
map<A, B>(f: (a: A) => B, fa: ?): ?
}
which is not possible in TypeScript since it does not support higher-kinded types or type parameters that take type parameters or parametrized modules.
- karmakaze 6y agoNot possible, but an approximation: interface Mappable<P extends Mappable<P, unknown>, T> { flatMap<U>(f: (x: T) => Mappable<P, U>): Mappable<P, U>; } class Maybe<T> implements Mappable<Maybe<unknown>, T> { x: T | undefined; public flatMap<U>(f: (x: T) => Maybe<U>): Maybe<U> { if (this.x) { return f(this.x); } return Maybe.nothing(); } }
- zcesur 6y agoYes, in fact this reminds me of the HKT implementation[1] found in fp-ts[2][3] interface HKT<F, A> { _URI: F _A: A } interface Mappable<F> { map<A, B>(f: (a: A) => B, fa: HKT<F, A>): HKT<F, B> } where F is a unique identifier representing the type constructor and A its type parameter. [1]: https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-kinded-polymorphism.pdf https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-ki... [2]: https://github.com/gcanti/fp-ts https://github.com/gcanti/fp-ts [3]: https://gist.github.com/gcanti/2b455c5008c2e1674ab3e8d5790cdad5 https://gist.github.com/gcanti/2b455c5008c2e1674ab3e8d5790cd...
- girvo 6y agogcanti’s work in Flow and Typescript is amazing and I use it daily :)
- elbear 6y agoSeems like something covered by typeclasses in Haskell, right?
- ratmice 6y agoSeems like it, but typeclasses are inherently anti-modular, they provide a globally coherent unique instance. consider the Ord typeclass giving a single ordering for a specific type. To reverse the order you need to create a new type with a new instance of ord which reverses it. Where in a module system its perfectly fine to have multiple instances of Ord for a given type. One gives global consistency where the other gives local consistency.
- elbear 6y agoWhen you put it like that, modules sound more powerful than typeclasses. Is there any situation where typeclasses are superior to modules?
- ratmice 6y agoI think the extra power comes with cognitive overhead, I.e. operators are now relative to some module, and you're stuck with that overhead whether or not you actually use the power or not. Trying to stay neutral, I think its no suprise that some people prefer typeclasses...
- zcesur 6y agoIn addition to @ratmice's comment, check out this post[1] on Existential Type. I've dabbled in Haskell myself with not much experience in ML, so I found it interesting to see how ML modules differ from Haskell typeclasses. Though they seem to be equi-expressive for the most part. [1]: https://existentialtype.wordpress.com/2011/04/16/modules-matter-most/ https://existentialtype.wordpress.com/2011/04/16/modules-mat...