我有一个关于Haskell中类型的初学者问题:有类似的函数:
f i xs = (sort xs) !! i
如何在不明确使用xs的情况下定义函数f0 xs = f 0 xs
?
刚刚接受
f0 = f 0
不起作用......
ghci向我展示了愚蠢的类型:
f :: Ord a => Int -> [a] -> a
f0 :: [()] -> ()
但是“:t f 0”给出了f 0 :: Ord a => [a] -> a
。
为什么?为什么我为f0获得此类型?为什么“f0”的类型和“f 0”的类型之间有什么区别?
非常感谢您提出任何建议
答案 0 :(得分:5)
它与您的特定定义无关:如果您使用标准实现(如您所愿!),同样的事情也会发生。
前奏>设f0 =最大
前奏> :t f0
f0 :: [()] - > ()
无论如何,首先你应该给f
签名。
f :: Ord a => Int -> [a] -> a
如果您也为f0
执行此操作,则一切正常:
f0 :: Ord a => [a] -> a
现在的问题是,为什么ghci会推断出如此愚蠢的签名?它是Dreaded Monomorphism Restriction的错。这意味着,每当你定义一些东西"作为常量( - applicative form)",即一个简单的等式
c = any odd stuff
然后编译器拒绝自动给出多态签名(例如,其中包含a
类型变量)。相反,它默认为"最简单的可用"类型,对于Ord
约束而言,遗憾的是它是完全无用的()
。
你可以关闭单态限制,即使没有签名也可以工作:
前奏> :set -XNoMonomorphismRestriction
前奏>设f0 =最大
前奏> :t f0
f0 :: Ord a => [a] - >一个
但老实说,无论如何,你应该始终使用手动签名。