簡體   English   中英

為什么這個Haskell代碼產生“無限類型”錯誤?

[英]Why does this Haskell code produce the “infinite type” error?

我是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(x:y:xs)”時,x和y成為列表 然而,我將x和y視為元素,而不是列表。

處理“無限類型”錯誤的指南:

大多數情況下,當你收到這個錯誤時,你已經忘記了你正在處理的各種變量的類型,並且你試圖使用一個變量,好像它是一些其他類型的變量。 仔細查看所有類型與您使用它的方式類型,這通常可以發現問題。

問題出在最后一個子句中,您將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,這意味着a是一個無限嵌套的列表。 這是不允許的(而不是你的意思,無論如何)。

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

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

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

看看當我讓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'

這清楚地指向代碼中的錯誤。 使用這種技術,您不必像其他人所建議的那樣盯着所有事物並仔細思考類型。

我可能錯了,但似乎你正試圖解決一個更難的問題。 你的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時希望我們做的事情。 當然,我可以完全退出。

我也發現解釋了錯誤的含義。

每次解釋器/編譯器都給我這個錯誤時,因為我使用了一些類型參數化的元組作為形式參數。 通過刪除包含類型變量的函數的類型定義,一切正常。

我仍然無法弄清楚如何修復它並保持函數類型定義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM