柯里化 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
标志),它会警告您没有类型签名的顶级名称。
我在 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
标志),它会警告您没有类型签名的顶级名称。