1

I have just started learning haskell and wrote a customized code for any function. Please suggest why does it still shows Non-exhaustive patterns error even after I have used otherwise or where I am going wrong?

Exceptiom raised :- Exception: main.hs:(37,1)-(40,21): Non-exhaustive patterns in function myAny

myAny :: (a -> Bool) -> [a] -> Bool
myAny f (x:xs)
  | f x == True = True
  | f x == False = myAny f xs
  | otherwise = False
  • 1
    And as it was said many times before: if you compile your code with `-W` flag you'd get a warning about it during the compilation instead of runtime error. The warning even tells you exactly what is missing: `Pattern match(es) are non-exhaustive In an equation for 'myAny': Patterns not matched: _ []` – Ed'ka Feb 18 '20 at 00:47

2 Answers2

6

You forgot to implement a clause for the empty list. Since you perform recursion, if none of the elements match, it will eventually call myAny with the empty list. In that case you need to return False:

myAny :: (a -> Bool) -> [a] -> Bool
myAny _ [] = False
myAny f (x:xs)
  | f x == True = True
  | f x == False = myAny f xs
  | otherwise = False

Note that it however makes no sense to perform two checks with f x, if it is not True, it is False, so the otherwise case will normally never occcur:

myAny :: (a -> Bool) -> [a] -> Bool
myAny _ [] = False
myAny f (x:xs)
  | f x = True
  | otherwise = myAny f xs

We can further simplify this with (||) :: Bool -> Bool -> Bool to:

myAny :: (a -> Bool) -> [a] -> Bool
myAny _ [] = False
myAny f (x:xs) = f x || myAny f xs

or use a foldr pattern:

myAny :: Foldable f => (a -> Bool) -> f a -> Bool
myAny f = foldr ((||) . f) False
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • If the short `foldr` version looks confusing, note that it's equivalent to `foldr (!!) False . map f`. `f` will be applied to values in the list as necessary, until `f` returns `True` or `foldr` exhausts the list. – chepner Feb 17 '20 at 13:27
  • Thanks for the detailed solution. Also, I used otherwise for any cases left, but it turn out it doesn't considers the case where the list is empty. – Sidharath Khanna Feb 18 '20 at 09:32
1

The problem here is that haskell cannot deconstruct [] into (x:xs), resulting in the case of an empty list not being covered.

A solution would be to specify:

myAny :: (a -> Bool) -> [a] -> Bool
myAny f (x:xs)
  -- ...
myAny f [] = False
Vogel612
  • 5,620
  • 5
  • 48
  • 73
  • Thanks for catching the exact error. Now I got why even after using otherwise, my code wan't considering the case with an empty list. – Sidharath Khanna Feb 18 '20 at 09:41