任何人都可以解释为什么haskell在以下示例中强制执行显式类型签名以及如何修改它以避免需要显式声明?
import qualified Data.List as L
main = do
print $ length $ L.nub [1,1,2,3] -- 3, passed (Eq a, Num a) => [a]
print $ length $ L.nub [] -- ambiguous type error, passed (Eq a) => [a]
-- can help type system with explicit signature but how to avoid ?
print $ length $ L.nub ([] :: [Int])
令人惊讶的是,在ghci中以交互方式编写的相同代码没有歧义问题,并且打印零长度:
λ> :m +Data.List
λ> print $ length $ nub []
0 -- ?? can you explain ??
Update: 看起来甚至同样限制 Data.List.nub
长度函数不会停止关于模糊类型的投诉:
length' :: Eq a => [a] -> Int
length' [] = 0
length' (x:xs) = 1 + length' xs
main = do
print $ length' $ nub []
-- No instance for (Eq a0) arising from a use of ‘length'’
-- The type variable ‘a0’ is ambiguous
1 回答
问题是
[]
具有多态类型(Eq a) => [a]
. 由于length
不添加任何特定约束 .具体来说
length
的类型是:这比
nub
更宽容:编译器需要在那里使用
length
的特定实例,并且无法推断a
的类型 .现在您有两个选择:
在文件开头用
{-# LANGUAGE ExtendedDefaultRules #-}
打开ExtendedDefaultRules
扩展名 .明确:
... L.nub ([] :: [Int])
除非你完全理解consequences of the first one,否则我建议默认使用第二个 .