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

Owe*_*wen 8 haskell typeclass

我没想到以下代码可以工作:

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

main = do
    print (foo (read "7"))
Run Code Online (Sandbox Code Playgroud)

因为不可能根据代码完全推断出(读"7")的类型.但GHC(6.12.3)认为不然并打印14.

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

Tom*_*ett 12

这是由Haskell 对该Num默认规则引起的.如果你添加了

default (Double, Integer)
Run Code Online (Sandbox Code Playgroud)

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

main = do
  print (foo (read "7")) -- prints "14.0"
  print (foo (read "7.2")) -- prints "14.2"
Run Code Online (Sandbox Code Playgroud)

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

您可以像这样禁用默认值:

default ()
Run Code Online (Sandbox Code Playgroud)

这将强制您通过类型注释明确消除此类术语的类型:

print (foo (read "7" :: Int))
Run Code Online (Sandbox Code Playgroud)