2009-04-27 111 views
59

我是Haskell的新手,面臨着我無法理解的「無法構造無限類型」的錯誤。實際上,除此之外,我還無法找到這個錯誤甚至意味着什麼的好解釋,所以如果你能超越我的基本問題並解釋「無限類型」的錯誤,我會非常感激它。爲什麼Haskell代碼會產生「無限類型」錯誤?

下面的代碼:

intersperse :: a -> [[a]] -> [a] 

-- intersperse '*' ["foo","bar","baz","quux"] 
-- should produce the following: 
-- "foo*bar*baz*quux" 

-- intersperse -99 [ [1,2,3],[4,5,6],[7,8,9]] 
-- should produce the following: 
-- [1,2,3,-99,4,5,6,-99,7,8,9] 

intersperse _ [] = [] 
intersperse _ [x] = x 
intersperse s (x:y:xs) = x:s:y:intersperse s xs 

而這裏的試圖將其加載到解釋的錯誤:

Prelude> :load ./chapter.3.ending.real.world.haskell.exercises.hs 
[1 of 1] Compiling Main (chapter.3.ending.real.world.haskell.exercises.hs, interpreted) 

chapter.3.ending.real.world.haskell.exercises.hs:147:0: 
Occurs check: cannot construct the infinite type: a = [a] 
When generalising the type(s) for `intersperse' 
Failed, modules loaded: none. 

感謝。

-

下面是一些修正的代碼以及處理在Haskell 「無限型」 錯誤的一般準則:

更正代碼

intersperse _ [] = [] 
intersperse _ [x] = x 
intersperse s (x:xs) = x ++ s:intersperse s xs 

什麼問題是:

我的簽名狀態s第二個散佈的參數是列表。因此,當我模式匹配「s(x:y:xs)」時,x和y變成列表。然而,我將x和y當作元素,而不是列表。

指引爲應付「無限型」的錯誤:

大多數時候,當你得到這個錯誤,你忘了你的類型正在處理的各種變量,而你試圖使用一個變量,就好像它是一種其他類型的東西,而不是它的樣子。仔細查看一切是什麼類型與你如何使用它,這通常會發現問題。

+1

另一個好的提示:明確聲明類型。這給了編譯器一些東西來檢查。 – 2009-05-01 18:47:23

+1

所以這解決了這個問題,但爲什麼編譯器會說「不能構造無限類型?」。那是什麼意思?如果問題在於您試圖對不支持這些操作的類型執行操作,爲什麼編譯器不這樣說? – freedrull 2010-03-08 07:13:31

+9

+1爲問題的結構(問題糾正 - 問題是 - 準則) – Dacav 2010-05-27 09:36:51

回答

27

問題出現在最後一個小節中,您將x和y當作元素,而它們是列表。這將工作:

intersperse _ [] = [] 
intersperse _ [x] = x 
intersperse s (x:y:xs) = x ++ [s] ++ y ++ intersperse s xs 

發生無限類型錯誤的原因是:經營者有A型 - > [A] - > [A],當你把它當作[A] - > A - > [一] ,這意味着[a]必須用a來標識,這意味着a是無限嵌套的列表。這是不允許的(而不是你的意思,無論如何)。

編輯:在上面的代碼中還有一個錯誤。它應該是:

intersperse _ [] = [] 
intersperse _ [x] = x 
intersperse s (x:xs) = x ++ [s] ++ intersperse s xs 
2

我可能是錯的,但它似乎是你試圖解決一個更困難的問題。您的版本intersperse不僅僅是將數值與數組散佈在一起,而且還將其平滑到一個級別。

Haskell中的List模塊實際上提供了一個散佈函數。它將中的每個元素放入列表中。例如:

intersperse 11 [1, 3, 5, 7, 9] = [1, 11, 3, 11, 5, 11, 7, 11, 9] 
intersperse "*" ["foo","bar","baz","quux"] = ["foo", "*", "bar", "*", "baz", "*", "quux"] 

我假設這是你想做的事,因爲這就是我的教授希望我們當我學習Haskell做什麼。當然,我完全可以放棄。

0

另外我發現了this,它解釋了錯誤的含義。

每當解釋器/編譯器給我這個錯誤,這是因爲我使用了一些類型參數化的元組作爲形式參數。一切工作正常刪除該函數的類型定義,其中包含類型變量。

我仍然不知道如何解決它並保持函數類型定義。

3

通常添加一個顯式的類型定義可以使編譯器的類型錯誤消息更有意義。但在這種情況下,顯式類型會使編譯器的錯誤信息變得更糟。

看的時候,我讓GHC猜點綴的類型會發生什麼:

Occurs check: cannot construct the infinite type: a = [a] 
    Expected type: [a] -> [[a]] -> [[a]] 
    Inferred type: [a] -> [[a]] -> [a] 
In the second argument of `(:)', namely `intersperse s xs' 
In the second argument of `(:)', namely `y : intersperse s xs' 

這顯然對在代碼中的bug點。使用這種技術,您不必像所有其他人所暗示的那樣,盯着所有的東西並且認真思考類型。

相關問題