Reputation: 1045
The following Haskell program is broken, because it does an incomplete pattern binding:
main = do
[x] <- pure ["foo", "bar"]
print x
If you compile it, you'll get no warnings:
$ ghc -fwarn-incomplete-uni-patterns -o example example.hs
[1 of 1] Compiling Main ( example.hs, example.o )
Linking example ...
but if you run it you'll get:
example: user error (Pattern match failure in do expression at example.hs:2:3-5)
I would like to somehow get a compiler warning.
From the documentation, I would have thought -fwarn-incomplete-uni-patterns
would do it, since the do
block desugars to:
desugared = pure ["foo", "bar"] >>= \[x] -> print x
And indeed, adding that to the example file does produce a warning:
$ ghc -fwarn-incomplete-uni-patterns -o example example.hs
[1 of 1] Compiling Main ( example.hs, example.o )
example.hs:1:37: Warning:
Pattern match(es) are non-exhaustive
In a lambda abstraction:
Patterns not matched:
[]
_ : (_ : _)
How do I get a similar warning when I do the same thing inside a do
block?
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.3
Upvotes: 14
Views: 1053
Reputation: 7129
As for now, the only thing you can do in order to avoid bugs due to this quirk is to avoid monads with MonadFail
instance (in recent GHC versions incomplete bind patterns would then lead to a compilation error).
There is already an issue for this. There is also a statement defending this solution stating that it may be something completely desirable and therefore does not deserve a warning:
This is actually the right useful behavior. using things like
do Just x <- xs Just y <- ys return (x,y)
will do the right thing, failing if xs or ysresults in Nothing. for instance, in the list monad, it will create the cross product of the non Nothing members of the two lists. a parse monad may backtrack and try another route, the IO monad will create a useful (and deterministic/catchable) exception pointing to the exact file and line number of the pattern match. The do notation is the only place in haskell that allows us to hook into the pattern matching mechanism of the language in a general way.
Upvotes: 1