沒想到下面的代碼工作:爲什麼Haskell在讀取Num時顯示爲默認讀取Int?
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實例?
沒想到下面的代碼工作:爲什麼Haskell在讀取Num時顯示爲默認讀取Int?
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實例?
這是由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))
'(民一,閱讀)=> [Char] - > a'顯然是不明確的。它必須以某種方式決定,所以我猜'Int'恰好是'Num'的默認值。也許是因爲它是某種類型類的第一個實例?我要去手動搜索。這是一個有趣的問題。 – alternative 2011-05-28 23:46:41
只是爲了記錄:它默認爲'Integer',而不是'Int'。 – sepp2k 2011-05-29 16:34:22