2016-07-29 81 views
0

我有一个帮助函数库,我想导出curried版本。无法导出咖喱通用函数

它的一小块看起来是这样的:

export function curry2<A,B,C>(f: (x: A, y: B) => C): (x: A) => (y: B) => C { 
    return (a) => (b) => f(a, b) 
} 

function _push<A>(item: A, items: Array<A>): Array<A> { 
    return items.concat(item) 
} 

export const push = curry2(push) 

但是,这并不工作。流程抱怨表达curry2(push),他说:

- type parameter 'A' of function call. Missing annotation. 
- type parameter 'B' of function call. Missing annotation. 

所以,我想通过注释导出的标识符来解决这个问题:

export const push<A>: (item: A) => (items: Array<A>) => Array<A> 

但是,这并不工作,因为const表达式不能引入泛型类型变量。

所以我想我会为了导出实际功能,能够将其标注为:

export function push<A> (item: A): (items: Array<A>) => Array<A> { 
    return curry2(_push)(item); 
} 

但在这一点上,我基本上要咖喱对重新写一大块每个功能我想要导出。

有没有更好的方法来帮助Flow在常量表达式中填充导出的泛型类型变量?

回答

2

见我的答案在这里同样的问题:https://github.com/facebook/flow/issues/2165#issuecomment-236868389

这里的主要限制是Flow根本不会推断多态类型。特别是,只要它看到对多态函数的调用,就会立即使用新类型参数实例化类型参数,并且结果永远不会像Hindley-Milner系统(https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)那样“泛化”。

这种限制的原因是这种多态类型推断是不可判定的,具有子类型(参见Pierce,“有界量化是不可判定的”,POPL'92),子类型是JavaScript的必要特征(但不是那么多对于类似ML的语言)。

0

我怀疑是不是可以定义curry2功能不高kinded类型

type Function2<A, B, C> = (a: A, b: B) => C; 
type CurriedFunction2<A, B, C> = (a: A) => (b: B) => C; 

export function curry2<A, B, C>(f: Function2<A, B, C>): CurriedFunction2<A, B, C> { 
    return (a: A) => (b: B): C => f(a, b) 
} 

export const push = curry2(function <A>(item: A, items: Array<A>): Array<A> { 
    return items.concat(item) 
}) 

最后的定义是指push具有类型

push: CurriedFunction2<A, Array<A>, Array<A>> // <= higher kinded type? 
+0

这似乎有同样的问题。导出的'push'表示缺少类型参数A,B和C的注释。由于它是一个const声明,因此无法提供它们。 – Adam

+0

我的意思是,目前这是不可能的,Flow不支持更高的亲属类型 – gcanti