2010-07-25 34 views
1
class Visible a where 
toString :: a -> String 
size :: a -> Int 

intToString :: (Integral t) => t -> String 
intToString 0 = "0" 
intToString 1 = "1" 
intToString 2 = "2" 
intToString 3 = "3" 
intToString 4 = "4" 
intToString 5 = "5" 
intToString 6 = "6" 
intToString 7 = "7" 
intToString 8 = "8" 
intToString 9 = "9" 
intToString n 
| ((div n 10) == 0) = (intToString (mod n 10)) 
| otherwise   = (intToString (div n 10)) ++ (intToString (mod n 10)) 

现在诠释VS整数类实例

instance Visible Int where 
toString = intToString 
size n = length (toString n) 

给我约一个模糊的类型变量的错误在提示符下,如果我输入类似(的toString 55)

instance Visible Integer where 
toString = intToString 
size n = length (toString n) 

没有。

什么给?

+3

仅供参考,这里是你的intToString的另一种定义:'intToString = show' – luqui 2010-07-25 16:05:19

回答

0

我找到this link一个可能的解释。我认为文字的默认解释是ghci中的整数。但如果这样做不成立,ghci开始对他必须做出的字面解释(Int,Double,Float,...)感到困惑。 随后,他给出了有关歧义的错误。命令(toString (55:Int))不会产生错误,因为GHCi知道他必须将55解释为Int

应用此方法不是为特定类型的值,但另一个重载型,以 值即你的文字5.这 意味着Haskell有找出哪些具体的类型来选择 为在这种情况下“a”。 Haskell的类型类是开放的,并且它通常不随机 选择一个,如果多个可能匹配。在这种情况下,Integer(在你的第一个例子中)或Int(在你的第二个例子中)有一个实例 ,但 也可能是Float或Double的另一个例子。哪一个会是 是正确的?那么,正如我所说的,通常哈斯克尔在这里保守,并且只是抱怨,因此在第二种情况下得到了“不明确类型变量”错误 。 但是,Haskell中有一种机制可以给出启发式规则,而 这就是“违约”的全部内容。在正常情况下,对于数字类型, 对于不明确的情况,在数字类型中选择“Integer”,如果不起作用,它将尝试“Double”。它不尝试“诠释” 虽然。这解释了为什么你的第一个例子(偶然)起作用。 如果你问GHCi的类型,默认不适用,但你可以观察到它发生在很多地方。例如,

15

这里有两件事情。请记住,Haskell中的数字文字是多态的。那就是:

x = 55 

的真正含义

x :: Num a => a 
x = fromIntegral 55 

这是任何你写他们所有的数字属实。这可能很难处理,所以GHCi实现了类型默认:如果类型不明确,它假定裸号是IntegersDoubles

当您在GHCi提示处编写toString 55时,GHCi推断数字55为(Visible a, Num a) => a。如果您只有Visible Int的范围,则缺省类型Integer不起作用,因为它没有满足类约束(没有Visible Integer),所以GHCi抱怨模糊类型变量,因为它不知道要实例化哪种类型为表达。如果你在范围内有Visible Integer,Integer默认的类型工作得很好。

如果你想使用整数以外的类型,你可以用一个明确的类型,如toString (55 :: Int)