caleborp
caleborp

Reputation: 145

Exception: Non-exhaustive patterns in function

Attempting to create a function that removes duplicates from a list, and replaces them with a single element. Keep getting an error message "Non-exhaustive patterns in function removeduplicate". I assume that means my pattern matching is missing a possible case? I think I've covered all the possibilities though. I'm very new to Haskell, so any help is greatly appreciated.

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])

Upvotes: 6

Views: 4879

Answers (2)

Daarx
Daarx

Reputation: 134

As Matt Bryant said, the particular compiler error stems from using [xs] instead of xs.

You actually have a redundant pattern in there, as well:

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

This line can be removed, because a pattern of type x:y:[] is already handled by

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

Since xs can be the empty list and removeduplicate [] resolves into [].

Keep in mind, though, that the code you provided only removes up to 2 successive duplicate elements. With three successive duplicates, two identical elements will be inserted into the result, which is probably not what you want.

A more complete function could look something like this:

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

Upvotes: 5

Matt Bryant
Matt Bryant

Reputation: 4961

Your problem is in your final pattern. I assume it is meant to match all lists, but the way you have it, it is matching a list with one element, xs, in it.

This means the compiler is seeing a match for a 3 element list, but not for an arbitrary length list, which is why it is complaining.

To fix this, remove the box around xs.

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

Now xs is treated as a list, so you are matching lists with at least three items, rather than just three items.

Upvotes: 12

Related Questions