我想定义一个map函数,它可以泛化任何容器。无论是数组,还是流,或者是可观察的,还是任何旧的monad等。
我认为为了对此进行建模,我需要某种形式的嵌套泛型。这样我就可以定义<T<U>>
。
let f : (
fn: (a:number) => string,
list:number[]
) => string[]
var toFixed = (a=0) => a.toFixed(2)
var list = [1,2,3]
f( toFixed , list ) //=> string[] ✓
// but what if I want to make the array's generic?
let f2 : <T,U>(
fn: (a:T) => U,
list:T[]
) => U[]
// that's simple
f2(toFixed, list) //=> string[] ✓
// but how do you support generic *containers*?
// so that instead of an array, its an Observable, or
// any Monad or Functor?
let f3 : <T,U, V> (
fn: (a:T) => U,
container: V<T>
) => V<U>
interface Observable <T> {}
interface Maybe <T> {}
interface Future<T> {}
let observable : Observable<number>
let maybe : Maybe<number>
let future : Future<number>
f3(toFixed, observable) // => any ✖
// We want it to be: Observable<string>
f3(toFixed, maybe) // => any ✖
// We want it to be: Maybe<string>
f3(toFixed, future) // => any ✖
// We want it to be: Future<string>
f3(toFixed, [1,2,3]) // => any ✖
// We want it to be: string[]
如果有另一种方法来模拟这种行为,我想听听任何替代方案。
答案 0 :(得分:0)
不完全是,但是您可以这样创建一个中间类型:
type Mappable<T> = {
map: <U>(fn: (t: T) => U) => Mappable<U>;
};
type map = <A, B>(fn: (a: A) => B) => (m: Mappable<A>) => Mappable<B>;
const map: map = (fn) => (m) => m.map(fn);
这样做会丢失一些类型信息(流/数组都将以可映射的形式出现),但是如果要泛型映射的类型有限,则可以通过推断或并集类型克服这种情况扩展可映射。