我在Haskell中手动编写currying函数如下。
curry f = \x y -> f(x,y)
然后我使用这个max(x, y) = if x > y then x else y
作为f,我写了max1 = curry max
来获得curried函数
但这是不允许的。为什么这是错的?
答案 0 :(得分:5)
你遇到了dreaded monomorphism restriction,它限制了Haskell推断多态类型的位置。
没有"外观"像一个函数 - 没有命名参数 - 不能有多态类型。问题是您的max
函数 具有多态类型(适用于o
类中的任何类型Ord
),这会强制类型系统为max1
选择一个概念可订购类型。由于没有要选择的默认类型,它会告诉您类型变量不明确。
有三种方法可以避免这种限制。正如您已经看到的那样,其中一个是使参数显式化,使整个绑定看起来像一个函数:
max1 x y = curry max x y
另一种是添加显式类型签名:
max1 :: Ord o => o -> o -> o
max1 = curry max
最后,您还可以通过在模块顶部添加编译器指令来关闭限制:
{-# LANGUAGE NoMonomorphismRestriction #-}
在所有这些中,最惯用的选择是添加类型签名。 通常,每个顶级名称都应该有一个显式的类型签名。这不是强制性的,但被认为是好的样式,因为除了避免单态问题,它还有助于捕获更多错误并使错误消息更容易阅读。如果您打开GHC中的所有警告(带有-Wall
标志),它将警告您没有类型签名的顶级名称。