2011-05-28 33 views
8

沒想到下面的代碼工作:爲什麼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實例?

+0

'(民一,閱讀)=> [Char] - > a'顯然是不明確的。它必須以某種方式決定,所以我猜'Int'恰好是'Num'的默認值。也許是因爲它是某種類型類的第一個實例?我要去手動搜索。這是一個有趣的問題。 – alternative 2011-05-28 23:46:41

+0

只是爲了記錄:它默認爲'Integer',而不是'Int'。 – sepp2k 2011-05-29 16:34:22

回答

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)) 
2

Int是此實例中的默認類型。見第二章。 6.3,Haskell歷史上的歧義和類型違約,與類一起懶惰,

+2

Noy'Int',但'Integer'是默認值。 – augustss 2011-05-29 08:32:17

+4

感謝您的參考。下面這句話清楚地說明了爲什麼他們會包含這樣一個非Haskell特性:「對常量進行數值計算是Haskell程序員所做的第一件事情之一」。所以ghci在2 + 2失敗可能會讓一些人失望。 – Owen 2011-05-31 22:44:00

相關問題