MFa*_*ave 1 javascript functional-programming hindley-milner
以下对 compose 函数的 Hindley-Milner 类型签名的尝试是否正确?
// compose :: (f -> [f]) -> (f -> f -> f) -> [f] -> f
const compose = (...fns) => fns.reduce((f,g) => (...args) => f(g(...args)));
Run Code Online (Sandbox Code Playgroud)
不,那是不正确的。您的compose
函数将一组函数作为输入,并生成一个(组合的)函数作为输出,因此签名显然是错误的。另一方面,我认为不可能使用 Hindley-Milner 类型系统编写该函数,除非您假设所有函数fns
都是相同类型的一元函数:(a -> a
即自同态数组)。
compose :: [a -> a] -> (a -> a)
Run Code Online (Sandbox Code Playgroud)
JavaScript 是动态类型的,所以它实际上允许每个函数fns
都是不同的类型(JS 不要求数组是同类的)。这意味着你可能需要发明一些新的语法来表达compose
你所拥有的类型。以下是Ramda(一个用于 JS 的函数式实用程序库)如何描述 的类型R.compose
:
((y ? z), (x ? y), …, (o ? p), ((a, b, …, n) ? o)) ? ((a, b, …, n) ? z)
Run Code Online (Sandbox Code Playgroud)
它使用此…
语法来表示可变参数函数。参数列表中最右边的函数是 类型((a, b, …, n) ? o)
,这意味着它是一个返回o
. 这o
随后被用作下一个函数,它是类型的输入(o ? p)
。这将继续向下传递参数列表,直到最左边的函数的类型为(y ? z)
,其中z
成为调用返回函数的结果类型:((a, b, …, n) ? z)
。