Question re "Pattern match(es) are non-exhaustive"

I understand the meaning of the warning, but got it in a situation I didn't expect. The following source file contains the simplest case I could construct quickly to illustrate my question: Why does the first function (sumDigits) get the "non-exhaustive" warning? It contains a definition for both empty and non-empty arguments, just as the second (sumList), which does not get a warning. {-# OPTIONS_GHC -Wall #-} sumDigits :: [Integer] -> Integer sumDigits [] = 0 sumDigits (n:ns) | n < 10 = n + sumDigits ns | n >= 10 = r + sumDigits (q : ns) where (q, r) = n `quotRem` 10 sumList :: [Integer] -> Integer sumList [] = 0 sumList (n:ns) = n + sumList ns For completeness, here is the ghci transcript, with the location reported: Prelude> :load sumDigits.hs [1 of 1] Compiling Main ( sumDigits.hs, interpreted ) sumDigits.hs:4:1: Warning: Pattern match(es) are non-exhaustive In an equation for ‘sumDigits’: Patterns not matched: _ : _ Ok, modules loaded: Main. Thanks in advance for any guidance on this. -jn- -- Beauty of style and harmony and grace and good rhythm depend on simplicity. - Plato

On Tue, Feb 10, 2015 at 6:58 AM, Joel Neely
{-# OPTIONS_GHC -Wall #-}
sumDigits :: [Integer] -> Integer sumDigits [] = 0 sumDigits (n:ns) | n < 10 = n + sumDigits ns | n >= 10 = r + sumDigits (q : ns) where (q, r) = n `quotRem` 10
sumList :: [Integer] -> Integer sumList [] = 0 sumList (n:ns) = n + sumList ns
ghc can't decide whether or not the tests in the guards are complete or not. If you rewrite the second condition as "otherwise", it'll recognize the catch-all and you won't get a warning.

On Tue, Feb 10, 2015 at 8:18 AM, Mike Meyer
ghc can't decide whether or not the tests in the guards are complete or not.
Expanding on this: that < and >= cover all cases is something that is convention for Ord instances, not something absolutely guaranteed to be true. (In fact, they *don't* cover all cases for IEEE floating point math, if either value is NaN. An SQL numeric value type would also not cover all cases because of the behavior of NULL. In both those cases, *both* conditions would return False.) The fact that you specified a type for which it does happen to be true doesn't really matter, because there's no way to convey a proof to the compiler that it's true for some types but not others. (Some argue that this and some other things are signs that the Ord typeclass is poorly designed; that is a fairly complex discussion.) A compiler for something like C would assume that it covers all types (and then behave weirdly in the above mentioned cases. Somewhat infamously, there was a longstanding bug in a standard C library function (qsort()) for decades because of this); Haskell compilers are a bit more pedantic and warn you that Ord provides no proof that those two conditions cover all cases. -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

On 2015-02-10 14:52, Brandon Allbery wrote:
On Tue, Feb 10, 2015 at 8:18 AM, Mike Meyer
wrote: ghc can't decide whether or not the tests in the guards are complete or not.
Expanding on this: that < and >= cover all cases is something that is convention for Ord instances, not something absolutely guaranteed to be true. (In fact, they *don't* cover all cases for IEEE floating point math, if either value is NaN. An SQL numeric value type would also not cover all cases because of the behavior of NULL. In both those cases, *both* conditions would return False.) The fact that you specified a type for which it does happen to be true doesn't really matter, because there's no way to convey a proof to the compiler that it's true for some types but not others. (Some argue that this and some other things are signs that the Ord typeclass is poorly designed; that is a fairly complex discussion.)
Interesting! This got me thinking - is this issue because the compiler doesn't (cannot?) see the implementation of e.g. (<=)? I noticed that a similiar case exists with f :: Bool -> Bool f x | x = True | not x = False ...which yields the same warning. I suppose this is because the compiler doesn't know the definition of 'not' so it doesn't understand that either of the two guards will always be True. Is there some technical reason for this - maybe it's very time consuming prove that the guards are exhaustive? -- Frerich Raabe - raabe@froglogic.com www.froglogic.com - Multi-Platform GUI Testing

On Tue, Feb 10, 2015 at 11:14 PM, Frerich Raabe
Interesting! This got me thinking - is this issue because the compiler doesn't (cannot?) see the implementation of e.g. (<=)?
It "sees" the implementation of (<=) for otherwise it won't be able to generate code for it. But see below.
I noticed that a similiar case exists with
f :: Bool -> Bool f x | x = True | not x = False
...which yields the same warning. I suppose this is because the compiler doesn't know the definition of 'not' so it doesn't understand that either of the two guards will always be True.
Again, it has to "know" the definition of the function "not" because it has to generate code to call it. But it doesn't "know" the function from any other function, say foo. Semantically speaking, both are equally opaque. Now you could point out that "Ah, but look at the definition of not. It could inline, simplify, et voila, obtain f True = True f False = False and hence pattern-matching is complete." Therein lies the rub. All that inlining and simplification boils down to evaluating the program _in_ the compiler, so if your program diverges so would the compiler, which wouldn't be a happy thing. -- Kim-Ee

On 2015-02-10 18:01, Kim-Ee Yeoh wrote:
On Tue, Feb 10, 2015 at 11:14 PM, Frerich Raabe
wrote: I noticed that a similiar case exists with
f :: Bool -> Bool f x | x = True | not x = False
[..]
Now you could point out that "Ah, but look at the definition of not. It could inline, simplify, et voila, obtain
f True = True f False = False
and hence pattern-matching is complete."
Therein lies the rub. All that inlining and simplification boils down to evaluating the program _in_ the compiler, so if your program diverges so would the compiler, which wouldn't be a happy thing.
Ah, true. The compiler would need to evaluate the program, I didn't realize that. But: what do you mean by 'if your program diverges' -- diverges from what? -- Frerich Raabe - raabe@froglogic.com www.froglogic.com - Multi-Platform GUI Testing

On Wed, Feb 11, 2015 at 3:24 PM, Frerich Raabe
Ah, true. The compiler would need to evaluate the program, I didn't realize that. But: what do you mean by 'if your program diverges' -- diverges from what?
http://en.wikipedia.org/wiki/Divergence_%28computer_science%29 -- Kim-Ee

On Tue, Feb 10, 2015 at 7:58 PM, Joel Neely
sumDigits (n:ns) | n < 10 = n + sumDigits ns | n >= 10 = r + sumDigits (q : ns) where (q, r) = n `quotRem` 10
To reiterate what Mike and Brandon just said, it's not that both the [] and (n:ns) cases have not been covered. They have. It's that the (n:ns) case hasn't been covered completely because of the guards. This will work: sumDigits (n:ns) | n < 10 = n + sumDigits ns | otherwise = r + sumDigits (q : ns) As will this: sumDigits (n:ns) | n < 10 = n + sumDigits ns | n >= 10 = r + sumDigits (q : ns) | otherwise = error "will never fire, only to suppress spurious warning" There's also -fno-warn-incomplete-patterns. -- Kim-Ee

Thanks for all the good explanations! I was misdirected by the fact that
the warning location was on the empty case, but based on descriptions I
think I understand why now.
I find it interesting that there is a bit of a conflict between "good
practice" heuristics:
1. Use -Wall (to eliminate questionable code that triggers warnings), and
2. Avoid _ in patterns in favor of explicit statement of the cases.
So it would appear that the advice (per Kim-Ee) to add an "otherwise" as a
third guard allows me to satisfy the compiler while documenting to the
human reader that the definition is really complete without it.
Thanks,
-jn-
On Tue, Feb 10, 2015 at 9:52 AM, Kim-Ee Yeoh
On Tue, Feb 10, 2015 at 7:58 PM, Joel Neely
wrote: sumDigits (n:ns) | n < 10 = n + sumDigits ns | n >= 10 = r + sumDigits (q : ns) where (q, r) = n `quotRem` 10
To reiterate what Mike and Brandon just said, it's not that both the [] and (n:ns) cases have not been covered. They have.
It's that the (n:ns) case hasn't been covered completely because of the guards.
This will work:
sumDigits (n:ns) | n < 10 = n + sumDigits ns | otherwise = r + sumDigits (q : ns)
As will this:
sumDigits (n:ns) | n < 10 = n + sumDigits ns | n >= 10 = r + sumDigits (q : ns) | otherwise = error "will never fire, only to suppress spurious warning"
There's also -fno-warn-incomplete-patterns.
-- Kim-Ee
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Beauty of style and harmony and grace and good rhythm depend on simplicity. - Plato

On Wed, Feb 11, 2015 at 12:11 AM, Joel Neely
So it would appear that the advice (per Kim-Ee) to add an "otherwise" as a third guard allows me to satisfy the compiler while documenting to the human reader that the definition is really complete without it.
Thanks for the citation! But if you look at lots of haskell code, I don't think there's One Best Style on how to write haskell. E.g. I hardly ever use guards and I'm far from being alone. For the code in question I'd probably have ended up with an if expression, although I do see the structural elegance that guards bring here. Another e.g. some will argue that the "right" approach is to collapse to 2 guards with the otherwise in the 2nd one. So the reader is expected to infer in a snap that if n is not < 10 then obviously it's >= 10. A "strong opinions, weakly held" strategy might work best. Be bold, make choices, trust in the warm diversity of the haskell universe. Don Stewart has a nice list of coding styles here: http://stackoverflow.com/a/6399082 -- Kim-Ee
participants (5)
-
Brandon Allbery
-
Frerich Raabe
-
Joel Neely
-
Kim-Ee Yeoh
-
Mike Meyer