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:
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"