柯里化 Haskell

Currying in Haskell

我在 Haskell 中手动编写了一个柯里化函数,如下所示。 curry f = \x y -> f(x,y) 然后我用这个 max(x, y) = if x > y then x else y 作为 f,我写 max1 = curry max 得到柯里化函数

但这是不允许的。为什么错了?

你 运行 进入 dreaded monomorphism restriction,这限制了 Haskell 可以推断多态类型的地方。

不像函数那样 "look" 的绑定——没有命名参数——不能有多态类型。问题是您的 max 函数 确实 具有多态类型(它适用于 Ord [=36= 中的任何类型 o ]),这会强制类型系统为 max1 选择一个具体的可订购类型。由于没有默认类型可供选择,它告诉您类型变量不明确。

您可以通过三种方式避免此限制。一种,正如您已经看到的,是使参数显式化,使整个绑定看起来像一个函数:

max1 x y = curry max x y

另一种是添加显式类型签名:

max1 :: Ord o => o -> o -> o
max1 = curry max

最后,您还可以通过在模块顶部添加编译器指令来关闭限制:

{-# LANGUAGE NoMonomorphismRestriction #-}

在所有这些中,最惯用的选择是添加类型签名。 一般来说,每个顶级名称都应该有一个明确的类型签名。这不是强制性的,但被认为是一种很好的风格,因为除了避免单态问题外,它还有助于捕获更多错误并使错误消息更易于阅读。如果您打开 GHC 中的所有警告(使用 -Wall 标志),它会警告您没有类型签名的顶级名称。