2013-08-01 53 views
4

嘗試創建一個從列表中刪除重複項並用單個元素替換它們的函數。繼續收到錯誤消息「函數removeduplicate中的非窮舉模式」。我認爲這意味着我的模式匹配缺少可能的情況?我想我已經涵蓋了所有可能性。我對Haskell很新,所以任何幫助都非常感謝。例外:函數中的非窮盡模式

removeduplicate :: (Eq a) => [a] -> [a] 
removeduplicate [] = [] 
removeduplicate (x:[]) = [x] 
removeduplicate (x:z:[]) = if z == x then [x] else (x:z:[]) 
removeduplicate (x:y:[xs]) 
    | x == y = x:(removeduplicate [xs]) 
    | otherwise = x:y:(removeduplicate [xs]) 

回答

10

您的問題是在您的最終模式。我假設它的意思是匹配所有列表,但是你擁有它的方式是匹配一個列表,其中包含一個元素xs

這意味着編譯器看到3個元素列表的匹配,但不是任意長度的列表,這就是爲什麼它抱怨。

要解決此問題,請移除圍繞xs的框。

removeduplicate (x:y:xs) 
    | x == y = x:(removeduplicate xs) 
    | otherwise = x:y:(removeduplicate xs) 

現在xs被視爲一個列表,讓你與至少三個項目,而不是僅僅三個項目匹配的列表。

5

正如Matt Bryant所說,特定的編譯器錯誤源於使用[xs]而不是xs

實際上,你在那裏有一個多餘的模式,以及:

removeduplicate (x:z:[]) if z == x then [x] else (x:z:[]) 

這條線可以去掉,因爲x:y:[]類型的模式已經被

removeduplicate (x:y:xs) 
    | x == y = x:(removeduplicate xs) 
    | otherwise = x:y:(removeduplicate xs) 

處理由於xs可空列表和removeduplicate []解析爲[]

請記住,您提供的代碼只能刪除最多2個連續的重複元素。隨着三個連續的重複,兩個相同的元素將被插入到結果中,這可能不是你想要的。

比較完善的功能可能是這個樣子:

removeduplicate []  = [] 
removeduplicate (x:xs) = x:(removeduplicate $ dropWhile (== x) xs)