2017-09-13 77 views
3

我有以下類型:如何使用類型和爲什麼編譯器抱怨無限類型?

newtype Moi s a = 
    Moi { runMoi :: s -> (a, s) } 

數據構造函數需要一個函數作爲參數,它應該返回一個元組。

我嘗試以下操作:

*OwnState> :t Moi (+1) 

編譯器會抱怨:

*OwnState> :t (+1) 
(+1) :: Num a => a -> a 

類型a必須是制約:

<interactive>:1:6: error: 
    * Occurs check: cannot construct the infinite type: s ~ (a, s) 
     Expected type: s -> (a, s) 
     Actual type: (a, s) -> (a, s) 
    * In the first argument of `Moi', namely `(+ 1)' 
     In the expression: Moi (+ 1) 

(+1)類型簽名首先看Num typeclass。

所以當我寫Moi (+1)時,會發生什麼,類型將如何替代?

讓我們來分析錯誤信息作爲下一步:

Occurs check: cannot construct the infinite type: s ~ (a, s) 

波浪號意味着~類型平等和編譯器如何來的結論,即s具有相同的類型(a, s)

我想,上面的例子中的類型替代工作在這樣:

n -> n "Type of (+1) 
| | 
s -> (a, s) 

然後s變得(a, s)和論證s ~ (a, s)是真實的。

(a, s) -> (a, s) 

但我看不出來,爲什麼它是無限的類型。

+1

因爲's'上的左側和右側都發生它是無限的'〜'而不是在語義部分。因此,在一次置換後,它是'〜(a,s)〜(a,(a,s))'等。 –

+1

's〜(a,s)'不正確 - 統一失敗檢查「步驟。事實上,沒有類型'T',其中'(a,T)'仍然是相同的類型:第二個直觀地包含另外一個'a'。這就像解決數字上的'n = n + 1'一樣:除非你以某種方式允許「無限」作爲數字,否則它是無法解決的。 – chi

+0

@Willem Van Onsem您可以爲我這樣的學習者展示如何替換一個類型。我看到很多案例,如何替代作品,但不知道,如果我是對的。 –

回答

7

但我看不出來,爲什麼它是無限的類型。

因爲s發生在類型相等~的左側和右側,並且這是遞歸方式。一個替代後,我們有:

s ~ (a,s) 

但需要注意的是s(a,s)也應該被替換,所以:

s ~ (a,s) ~ (a,(a,s)) ~ (a,(a,(a,s))) ~ ... 

因此,爲了構建這種類型的話,就會造成一種具有無限嵌套2元組。 Haskell無法處理這種類型。

Moi (+1)只是不符合這個「狀態monad」的規格。你可能想使用:

Moi (\x -> (x,x+1)) 

或:

Moi (ap (,) (1 +)) 
相關問題