Ticket #5813 (new feature request)

Opened 16 months ago

Last modified 8 months ago

Offer a compiler warning for failable pattern matches

Reported by: snoyberg Owned by:
Priority: normal Milestone: 7.6.2
Component: Compiler Version: 7.2.2
Keywords: Cc: Christian.Maeder@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

This started off with a mailing list discussion:  http://www.mail-archive.com/haskell-cafe@haskell.org/msg96517.html. The problem is that the following code produces no compile-time warning and results in a runtime error:

data MyType = Foo | Bar
    deriving Show

test :: Monad m => m MyType -> m ()
test myType = do
    Foo <- myType
    return ()

main :: IO ()
main = test $ return Bar

This is in contrast to the rest of pattern matching, which would warn about unmatched patterns, e.g.:

data MyType = Foo | Bar
    deriving Show

test :: Monad m => m MyType -> m ()
test myType = do
    x <- myType
    case x of
        Foo -> return ()

main :: IO ()
main = test $ return Bar

I understand that this style of code may be very useful in some circumstances when paired with a Monad providing a sensible fail implementation, and is especially used in list comprehensions. However, this is allowing an easily catchable static error to slip through our fingers.

I recommend we add a new compiler warning to catch incomplete patterns in do-notation binding. I believe this warning should not apply to list comprehensions. Ideally, this warning would be turned on by -Wall.

Change History

  Changed 16 months ago by snoyberg

  • type changed from bug to feature request

  Changed 16 months ago by igloo

  • difficulty set to Unknown
  • milestone set to 7.6.1

I'd be inclined to close this as wontfix, as John explains in  http://www.mail-archive.com/haskell-cafe@haskell.org/msg96527.html :

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.

What do other people think?

  Changed 16 months ago by snoyberg

Dynamic typing is also a "right useful behavior" for some people. It can remove the need for some typing (both meanings intended) and make code shorter. Critics of dynamic typing generally counter that static typing can move a whole class of errors from runtime bugs to things which can be caught at compile time. I believe the same logic applies here.

I'm not arguing to have this behavior removed from GHC; I'm asking for an option to be added for those of us wanting a little more safety in our code.

  Changed 16 months ago by maeder

  • cc Christian.Maeder@… added

I think, it is definitely worth a flag, since you get a warning if you desugar "do" manually to "... >>= \ (Just y) -> ...".

follow-up: ↓ 6   Changed 16 months ago by simonmar

For things like this we usually add a warning flag, but do not include it in -Wall. We have a bunch of flags in this category already (cut/pasted from the docs):

            <option>-fwarn-tabs</option>,
            <option>-fwarn-incomplete-uni-patterns</option>,
            <option>-fwarn-incomplete-record-updates</option>,
            <option>-fwarn-monomorphism-restriction</option>,
            <option>-fwarn-unrecognised-pragmas</option>,
            <option>-fwarn-auto-orphans</option>,
            <option>-fwarn-implicit-prelude</option>.</para>

In reply to maeder: the manual desugaring you describe is not semantics-preserving, so it's not surprising that you suddently get a new warning.

in reply to: ↑ 5   Changed 16 months ago by maeder

Replying to simonmar:

In reply to maeder: the manual desugaring you describe is not semantics-preserving, so it's not surprising that you suddently get a new warning.

I know, the missing cases are turned into nice _fail_ message (including the file position) that I would like to create explicitly by a suitable (non-pure?) function.

  Changed 16 months ago by snoyberg

Having a flag at all would definitely be an improvement. I would still prefer that it be on with -Wall, but I understand the hesitation in doing so.

  Changed 8 months ago by igloo

  • milestone changed from 7.6.1 to 7.6.2
Note: See TracTickets for help on using tickets.