Haskell Num类和我的类似show类之间的歧义

时间:2011-05-17 06:23:31

标签: haskell types default typeclass

我正在尝试使用适当的转换声明我自己的数据作为类。我的代码如下所示:

data SomeData =  SInteger Integer | SElse deriving Show

class Some a where
    toSome :: a -> SomeData

instance Some Int where toSome = SInteger . toInteger

main :: IO ()
main = print $ toSome 3

但是GHC(7.0.3)变得生气并说:

Ambiguous type variable `a0' in the constraints:
      (Some a0) arising from a use of `toSome'
                at minimal_broken.hs:11:16-21
      (Num a0) arising from the literal `3' at minimal_broken.hs:11:23
    Probable fix: add a type signature that fixes these type variable(s)

显式类型签名(如3 :: Int)修复了这个问题,但是非常不方便 标准的“显示”工作正常,根据手册,它的声明方式完全相同。

为什么标准节目有效,但我的课程没有?我错过了什么吗?

P.S。:明确的“默认(Int)”无法解决此问题。

3 个答案:

答案 0 :(得分:4)

你对超载是正确的。这有点棘手。首先,必须提供类型签名以解决示例中的数字重载:

Ambiguous type variable `a0' in the constraints:
  (Some a0) arising from a use of `toSome' at A.hs:11:16-21
  (Num a0) arising from the literal `3' at A.hs:11:23

这意味着,正如您所注意到的那样,您必须选择特定的解决方案类型,例如Int。

那么Show如何运作?通过扩展违约规则的魔力。 Show很特别,GHCi启用了一些特殊的默认规则来帮助“默认”type in arguments of Show to Integer

您的新课程不是扩展默认功能所知道的神奇课程之一,所以遗憾的是,您需要提供类型注释。

答案 1 :(得分:1)

show 3之类的工作原因首先是由于默认规则在涉及Num类时存在歧义时选择特定类型。它不适用于你的Some类的原因是规则说所涉及的所有类都必须是标准类(即来自Prelude等)。这个规则的后半部分有些愚蠢。

答案 2 :(得分:0)

问题:3的类型是Num a => a,但ghc需要具体类型才能搜索Some的实例 (可能,Some中可能存在多个Num的实例 - 所以选择哪一个?)