2014-05-21 30 views
1

誰能告訴我哪裏出了問題?米蘭達類型錯誤

b f x = f x (f x) 

我的理解是:因爲f在左側有一個參數,但在右側有兩個參數?

更詳細的解釋?

+1

'f'不會「在左邊帶參數」。 'x'不是LHS中'f'的參數。 – user2407038

回答

2

讓我們嘗試構建類型:

b :: ... ? 

我們至少有兩個參數,所以讓我們改變b相應:

b :: a -> c -> d 

b右手邊認爲,f是一個函數。讓我們首先關注的只有第一個參數:

f :: c -> e 

到現在爲止,一切都適合相當不錯:列表的第一個參數具有相同的類型B的第二個參數。讓我們繼續在右側。

f x (f x) 

如果我們把f x _,我們必須假設ee :: k -> l,那就是,我們採取另一種說法。我們現在有

f :: c -> k -> l 

現在看看f的第二個參數的類型。它的類型應該是f x之一:

f x :: k -> l 

所以k = k -> l。這是一個無限的類型,我們也可以通過查看ghci中的錯誤信息,請參閱:

Prelude> let b f x = f x (f x) 

<interactive>:2:18: 
    Occurs check: cannot construct the infinite type: t1 = t1 -> t0 
    In the return type of a call of `f' 
    Probable cause: `f' is applied to too few arguments 
    In the second argument of `f', namely `(f x)' 
    In the expression: f x (f x) 

類型檢查放棄,因爲無限的類型不能由它來構建。最後,這是因爲您對不同數量的參數應用f

1

編譯器試圖推斷出f的類型。首先它看到f採用參數x和另一個參數(f x),現在我們將替換爲y。因此,當編譯器看到類似f x y的東西時,它推斷f的類型爲a -> b -> c,其中x :: ay :: bf x y :: c。然後它檢查y更接近,看到它的類型更具體地b -> c,因爲它已經知道f必須有第二個參數。所以現在可以確定b ~ b -> c。這是它必須停止的地方,b怎麼樣也是b -> c?如果它一直代替b ~ b -> c,它會有一個無限遞歸試圖找出什麼類型b是!這顯然不能工作,所以它會拋出一個編譯錯誤,說它不能構造無限類型b = b -> c(注意:錯誤消息可能使用與bc不同的名稱)。該錯誤消息我得到的實際上是相當有幫助的:

Occurs check: cannot construct the infinite type: t1 = t1 -> t0 
In the return type of a call of `f' 
Probable cause: `f' is applied to too few arguments 
In the second argument of `f', namely `(f x)' 
In the expression: f x (f x) 

這告訴你到底哪裏出了問題「即(f x)」,併爲您提供可能的原因「f應用於參數太少」,說它「不能構造無限類型t1 = t1 -> t0」。