2010-07-24 42 views
3

同時通過真實世界哈斯克爾工作,我嘗試使用下面的代碼的解決方案來完成迴文鍛鍊:爲什麼這種形式可以接受,但另一種形式會引發類型錯誤?

palin :: [a] -> [a] 
palin list = list ++ rev list 
    where rev list 
      | null list = [] 
      | otherwise = rev (tail list) ++ (head list) 

其中提出了一個「無法構造無限類型的錯誤。然而,簡單地更換周圍的括號頭列表用方括號,它工作正常,如下面的例子證明:

palin :: [a] -> [a] 
palin list = list ++ rev list 
    where rev list 
      | null list = [] 
      | otherwise = rev (tail list) ++ [head list] 

我真的不明白,爲什麼它很重要,我也不明白什麼是「無法構造無限類型= [ a]「錯誤我答。有人能解釋這一點嗎?

+0

表達式'(something)** ** never **與形式'[something]'的相應表達式具有相同的類型,您只需用方括號替換括號即可。那*總是很重要! – Ben 2013-12-17 00:29:02

回答

10

在最後一行中,您嘗試將非列表追加到列表。 head list給出列表中的第一項,即a。當您嘗試使用++進行追加時,不能將不是列表的東西追加到列表中。通過附加[head list],您將一個項目的列表附加到另一個列表。在這種情況下,[]構造單個項目列表。

7

++運算符的類型爲[a] -> [a] -> [a],即它需要兩個某種類型的列表並生成另一個相同類型的列表。 OTOH head函數具有類型[a] -> a,即它接受某種類型的列表並返回該類型的值。在你的第一個例子++得到[a]在左邊和a在右邊。試圖統一這些類型檢查器會產生該錯誤。在第二個示例中,您從head的結果構建了單元素列表,並且它的類型爲[a],因此類型檢查器很高興。

10

假設你是類型檢查,您會看到這一點:

(tail list) ++ (head list) 

你已經知道,'名單的事情的清單。所以,你開始:

list::[a] 

那麼這一定是真實的:

(tail list)::[a] 

這:

(head list)::a 

但隨後有`++其希望它的兩個參數有相同的類型。但是,這意味着,

a == [a] 

或通過取代:

a == [a] == [[a]] == [[[a]]] ...etc. 

這確實是一個無限型。