我没想到以下代码可以工作:
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)