I am trying to implement a function called compress such that if a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed. For example:
λ> compress "aaaabccaadeeee"
"abcade"
I have two solutions, compress and compress’, that I thought are equivalent. However, compress’ works while compress gives the error: *Non-exhaustive patters in function*. I thought that compress will cover all cases, but I am not sure what went wrong. Thanks!
compress (x:ys@(y:_))
| null (x:ys) = []
| null ys = [x]
| x /= y = x : compress ys
| x == y = compress ys
λ\> compress "aaaabccaadeeee"
Non-exhaustive patterns in function compress
compress' (x:ys@(y:_))
| x == y = compress' ys
| otherwise = x : compress' ys
compress' ys = ys
λ\> compress' "aaaabccaadeeee"
"abcade"
edits: removed unintended forward slashes when writing in code block
>Solution :
Your pattern has two :, meaning it only matches lists with 2 or more elements. You still need definitions for empty and singleton lists:
compress [] = ...
compress [x] = ...
The various guards are all only applied to lists matching the pattern used in the single definition you provide. (In particular, note that null (x:ys) will never be true; null only returns true on [], not any list involving the : constructor.)
In compress', the irrefutable pattern y matches any list not matched by pattern in the first definition.