2013-03-02 30 views
4

考慮以下不良代碼推論:在如果......那麼......否則奇怪的行爲

fun x = 
    if (null x) then 0 
    else (take 50 x) : (fun (drop 50 x)) 

我注意到,我可以加載到ghci中沒有任何問題,這就是問題所在。
當我嘗試評估此功能時,該程序僅檢索到錯誤。

關於if ... then ... else表達式的默認推理規則,由於兩個分支顯式檢索不同的類型,爲什麼這個代碼可以加載(即編譯)?我的意思是,爲什麼編譯器無法弄清楚這個代碼是不合格的?

注意:當然,如果我爲這個函數添加了正確的類型註解,正如所期望的那樣它將被拒絕,但是根據我的理解,如果沒有類型註釋,它也應該被拒絕。

回答

16

Overloaded numeric literals。 Haskell數字文字是基於類型上下文定義的任何Num類的實例。

推斷類型解釋它:

Prelude> let f x = if null x then 0 else take 50 x : f (drop 50 x) 

Prelude> :t f 
f :: Num [[a]] => [a] -> [[a]] 

那讀作「如果你有民類的實例爲a列表的列表,那麼這個功能需要的清單,清單列表

因此,它依賴於Num的神話實例列表列表,如果您嘗試編譯使用此代碼的代碼,但未提供列表列表的數字實例,則會出現編譯錯誤

本例子o說明了爲什麼首先寫下類型簽名是一個好主意。

+3

要添加到Don的答案:理論上可以爲'[[a]]定義一個'Num'實例,在這種情況下,代碼將鍵入檢查並使用該'Num'實例來解釋數字文字' 0'。 – 2013-03-02 18:37:02

3

讓我們來看看。

Prelude> let fun x = if (null x) then 0 else (take 50 x) : (fun (drop 50 x)) 
Prelude> :t fun 
fun :: Num [[a]] => [a] -> [[a]] 

正如你所看到的編譯器,推測Num類的結果類型。