为什么Haskell在读Num时似乎默认为读取Int?

时间:2011-05-28 23:41:14

标签: haskell typeclass

我没想到以下代码可以运行:

foo :: (Num a) => a -> a
foo x = x + x

main = do
    print (foo (read "7"))

因为无法根据代码完全推断出(读取“7”)的类型。但GHC(6.12.3)认为不然并打印14。

如果“7”更改为“7.2”,则代码将失败并显示“no parse”。这里发生了什么? Haskell如何决定使用哪个Read实例?

2 个答案:

答案 0 :(得分:12)

这是由Haskell的defaulting rules for the Num class引起的。如果你添加了

default (Double, Integer)

到文件的顶部,然后你会得到以下结果:

main = do
  print (foo (read "7")) -- prints "14.0"
  print (foo (read "7.2")) -- prints "14.2"

简而言之,默认规则是尝试“尝试做正确的事情”并在程序中存在模糊类型时避免编译错误。不幸的是,在这种情况下,它会针对运行时错误交换编译时错误。

你可以像这样禁用默认:

default ()

会强制您通过类型注释明确消除此类术语的类型歧义:

print (foo (read "7" :: Int))

答案 1 :(得分:2)

Int是此实例中的默认类型。见第二节。 6.3,歧义和类型违约,在Haskell的历史中:与班级一起懒惰,