函数式 JavaScript:Compose 的 Hindley-Milner 类型签名是什么?

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)

4ca*_*tle 5

不,那是不正确的。您的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)