6

尝试创建一个从列表中删除重复项并将其替换为单个元素的函数。不断收到错误消息“已删除函数中的非详尽模式”。我认为这意味着我的模式匹配缺少可能的情况?我想我已经涵盖了所有的可能性。我对 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])
4

2 回答 2

12

您的问题出在您的最终模式中。我认为它是为了匹配所有列表,但你拥有它的方式,它匹配一个列表,其中包含一个元素 , xs

这意味着编译器看到的是一个 3 元素列表的匹配项,而不是一个任意长度的列表,这就是它抱怨的原因。

要解决此问题,请移除xs.

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

Nowxs被视为一个列表,因此您匹配的列表至少包含三个项目,而不是三个项目。

于 2013-08-01T01:51:41.443 回答
5

正如马特布莱恩特所说,特定的编译器错误源于使用[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)
于 2013-08-01T10:11:20.163 回答