Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get GHC to warn about incomplete pattern bindings in do blocks?

Tags:

haskell

ghc

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
like image 813
jml Avatar asked Jan 31 '26 04:01

jml


1 Answers

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.

like image 121
radrow Avatar answered Feb 01 '26 20:02

radrow