Reputation: 434
Consider a function disjoint :: (Eq a, Ord a) => [a] -> [a] -> Bool
which checks if there exists a common element between two sorted lists (and if it does, it returns False
since they wouldn't be disjointed).
disjoint :: (Eq a, Ord a) => [a] -> [a] -> Bool
disjoint [] _ = True
disjoint _ [] = True
disjoint (x:xs) (y:ys)
| x == y = False
| x < y = disjoint xs (y:ys)
| x > y = disjoint (x:xs) ys
In my IDE vscode
, it yields the following warning:
Pattern match(es) are non-exhaustive
In an equation for ‘disjoint’: Patterns not matched: (_:_) (_:_)compile(-Wincomplete-patterns)
Writing it in a different yet similar way, by using the otherwise
clause, will yield no errors:
disjoint :: (Eq a, Ord a) => [a] -> [a] -> Bool
disjoint [] _ = True
disjoint _ [] = True
disjoint (x:xs) (y:ys)
| x < y = disjoint xs (y:ys)
| x > y = disjoint (x:xs) ys
| otherwise = False
What "pattern" does the first code block "miss"? In other words, at what parameters will the first block of code have problems with?
Upvotes: 2
Views: 473
Reputation: 7014
Eq
is a superclass of Ord
so you can omit it from the constraint.
You can use compare
to turn it into data Ordering = LT | EQ | GT
which only has three cases, allowing the compiler to infer exhaustiveness.
disjoint :: Ord a => [a] -> [a] -> Bool
disjoint [] _ = True
disjoint _ [] = True
disjoint (x:xs) (y:ys) =
case x `compare` y of
EQ -> False
LT -> disjoint xs (y:ys)
GT -> disjoint (x:xs) ys
Upvotes: 7
Reputation: 434
From @chi's comment here:
Consider the following data type:
data TT = Bogus
instance Eq TT where
Bogus == Bogus = False
instance Ord TT where
Bogus <= Bogus = False
Bogus < Bogus = False
Bogus >= Bogus = False
Bogus > Bogus = False
Any comparisons between a Bogus
and a Bogus
returns False
. Because of that,
> disjoint [Bogus, Bogus] [Bogus, Bogus]
*** Exception: Ch04Book.hs:(25,1)-(30,18): Non-exhaustive patterns in function disjoint
The same Exception is raised when running disjoint [acos 2] [acos 2]
since comparisons between NaN
s always returns False
.
Sidenote/implication: A type of typeclass Ord
does not necessarily follow the Law of excluded middle. See Bogus
where both Bogus < Bogus = False
and Bogus >= Bogus = False
, and Haskell would not complain.
Upvotes: 3