Home > OS >  Non-exhaustive patterns in function which is exhaustively defined
Non-exhaustive patterns in function which is exhaustively defined

Time:10-10

So i've come across this particular error. Searched the web but didn't find any matches. The weird part is that I can't understand how can it be non-exhaustive.

Here are the functions in cause:

myand :: [Bool] -> Bool
myand (x:xs) | null (x:xs) = True
             | null xs = x
             | otherwise = x && myand xs
myor :: [Bool] -> Bool
myor (x:xs) | null(x:xs) = False
            | null xs = x
            | otherwise = x || myor xs

safetail :: [a] -> [a]
safetail (x:xs) |null (x:xs) = []
                |otherwise = xs

These are very simple functions, defined in files, and all are generating the exception when I try to run them with the empty list.

Example run:

*Main> myor [True]
True
*Main> myor []
*** Exception: tp2.hs:(10,1)-(12,38): Non-exhaustive patterns in function myor
*Main> myor [True, False, True]
True

Weirdest part is the first two were running fine yesterday - and also generate the same error if "null (x:xs)" is substituted by "length (x:xs) == 0". I also find it interesting that the null (x:xs) = True works for the recursive case but not for the pure empty list case

CodePudding user response:

Rewriting these to use conditionals instead of guards, we get

myand (x:xs) = if null (x:xs) then True
               else if null xs then x
               else x && myand xs

myor (x:xs) = if null(x:xs) then False
              else if null xs then x
              else x || myor xs

safetail (x:xs) = if null (x:xs) then []
                  else xs

It is pretty clear that each definition has exactly one clause, with the pattern x:xs, and x:xs does not match the empty list.
(Note that null (x:xs) is never True, since x:xs is a list with at least one element.)

These are what you intended to match:

myand [] = True
myand [x] = x
myand (x:xs)  = x && myand xs

myor [] = False
myor [x] = x
myor (x:xs)  = x || myor xs

safetail [] = []
safetail (_:xs) = xs

Also note that myand and myor only need two clauses.

The reason that your functions don't fail when recursion reaches the empty list is that it doesn't reach it, due to your "exactly one element" guard, null xs.

myand [] = True
myand (x:xs)  = x && myand xs

myor [] = False
myor (x:xs)  = x || myor xs

CodePudding user response:

The problem is very apparent in Visual Studio Code / Haskell Language Server:

enter image description here

The item (x:xs) doesn't match [], since (x:xs) implies that it has at least one value:

matchit (x:xs) = "Match 1"
matchit lst = "Match 2"

-- matchit [] == "Match 2"
-- matchit [1] == "Match 1"
-- matchit [1,2] == "Match 1"
  • Related