【问题标题】:Ambiguous type variable but not in ghci?模棱两可的类型变量,但不在 ghci 中?
【发布时间】:2014-10-20 13:49:51
【问题描述】:

谁能解释为什么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 ??

更新: 它似乎与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

【问题讨论】:

  • ghci默认开启扩展默认规则(-XExtendedDefaultRules),见here,进入2.4.8节。
  • 谢谢。这是一个隐藏的标志,因为 ghci 不会用:show language 列出它我得到base language is: Haskell2010 with the following modifiers: -XNoDatatypeContexts -XNondecreasingIndentation
  • 我认为规则仅适用于交互式输入而不适用于加载的模块,因此真正的编译器标志不是“真正”打开。

标签: haskell


【解决方案1】:

问题在于[] 具有多态类型(Eq a) => [a]。由于length 没有添加任何特定的约束。

具体length的类型是:

length :: [a] -> Int

这比nub更宽松:

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

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

现在你有两个选择:

  1. 打开ExtendedDefaultRules 扩展名,文件开头带有{-# LANGUAGE ExtendedDefaultRules #-}
  2. 明确:... L.nub ([] :: [Int])

我默认推荐第二个,除非你完全理解consequences of the first one

【讨论】:

  • 感谢您的回答。你能否解释一下为什么像 length' :: Eq a => [a] -> a 这样同样专业的长度函数没有帮助,而且我仍然遇到模棱两可的类型错误?
  • @DavidUnric 因为编译器仍然无法推断出a,因为有> 1 种数据类型同样很好地满足Eq(双关语不是故意的)。请问你是在哪本书上学习 Haskell 的? AFAIK 大多数书籍在上半年都在谈论这个话题。
  • 当然有很多类Eq的实例,只是期望类型系统可以从[] :: Eq t => [t]推断出足够length作为泛型类型足以计算列表的长度。跨度>
  • @DavidUnric 泛型类型足以计算列表的长度,这就是标准长度函数没有 Eq 约束的原因!当您将 Eq 约束添加到您的版本时,您明确向 GHC 声明它需要提供一个 Eq 实例才能调用该函数。如果不知道a 是什么类型(或者被传递一些同样具有约束的 smae 类型),它就无法做到这一点。它假定您的意思是您所说的,而不是查看 length' 的定义以查看您并不“真正”需要该实例,因此它会出错。
  • re:“编译器需要在那里使用length 的特定实例”,你不是说nub吗?
猜你喜欢
  • 2012-12-18
  • 2012-10-18
  • 2010-09-30
  • 2018-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-23
相关资源
最近更新 更多