首页 文章

不明确的类型变量,但不是在ghci?

提问于
浏览
6

任何人都可以解释为什么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 回答

  • 10

    问题是 [] 具有多态类型 (Eq a) => [a] . 由于 length 不添加任何特定约束 .

    具体来说 length 的类型是:

    length :: [a] -> Int
    

    这比 nub 更宽容:

    nub :: Eq a => [a] -> [a]
    

    编译器需要在那里使用 length 的特定实例,并且无法推断 a 的类型 .

    现在您有两个选择:

    • 在文件开头用 {-# LANGUAGE ExtendedDefaultRules #-} 打开 ExtendedDefaultRules 扩展名 .

    • 明确: ... L.nub ([] :: [Int])

    除非你完全理解consequences of the first one,否则我建议默认使用第二个 .

相关问题