marowl
marowl

Reputation: 43

Non-exhaustive pattern

I wrote a function that would take a list [a] and would group all equal values into another list - so the output would be something like [[a]]. Now I used ghci with (-W) Warnings enabled, and it seems one of my patterns isn't exhaustive - could you help me find the case my pattern doesn't match yet ? <3

h :: Eq a => [a] -> [[a]]
h [] = []
h (x:xs) = help x xs [x] []
 where help :: Eq a => a -> [a] -> [a] -> [a] -> [[a]]
       help _ [] s [] = [s]                            --line 15
       help _ [] s n = s : (h n) 
       help a (y:ys) s n | a == y = help a ys (y:s) n
                         | a /= y = help a ys s (y:n)
test.hs:15:8: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘help’: Patterns not matched: _ (_:_) _ _
   |
15 |        help _ [] s [] = [s]
   |        ^^^^^^^^^^^^^^^^^^^^...

Upvotes: 3

Views: 114

Answers (1)

Basically, because it's technically possible that neither of your guards a == y or a /= y are true.

Even though it's commonly assumed that Eq means an equivalence relation, the Haskell Report actually doesn't define any laws for it. In particular, the "custom" x /= y = not (x == y) can be violated. (And even if it were a law, those still aren't enforced by the compiler.) Consider this:

data BadIdea = BadIdea

instance Eq BadIdea where
    _ == _ = False
    _ /= _ = False

Although you really shouldn't do that, you can, and then your program would crash since neither case was true.

The easiest way for you to fix this is to replace a /= y with otherwise. This is analogous to the fact that you wouldn't write if a == y then ... and if a /= y then ... but would rather write if a == y then ... else .... Since in practice, no real types have an Eq instance that's so pathological, this won't really change your program's behavior (and if you did use such a type, it would just consider them unequal instead of crashing).

Upvotes: 4

Related Questions