我正在尝试使用适当的转换声明我自己的数据作为类。我的代码如下所示:
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)”无法解决此问题。
答案 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
的实例 - 所以选择哪一个?)