Asked  6 Months ago    Answers:  5   Viewed   20 times

Is there a way to get GHCi to produce better exception messages when it finds at runtime that a call has produced value that does not match the function's pattern matching?

It currently gives the line numbers of the function which produced the non-exhaustive pattern match which though helpful at times does require a round of debugging which at times I feel is doing the same set of things over and over. So before I tried to put together a solution I wanted to see if something else exists.

An exception message that in addition to giving the line numbers shows what kind of call it attempted to make?

Is this even possible?

 Answers

45

Try turning on warnings in ghci. This enables the compile time warnings you can get with ghc by passing -W, for example. You can do this several ways:

ghci -fwarn-incomplete-patterns

Or Neil Mitchell describes how he sets this up in his .ghci. Here is the relevant excerpt:

:set -fwarn-incomplete-patterns

You can manually enter this at ghci as well, but it would be a pain to do so each time you start it. Entered this way, it only works for statements entered at the prompt, not for loading files with :l. Instead you can put this comment at the top of the file you want to warn about incomplete patterns:

{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
Tuesday, June 1, 2021
 
uiroshan
answered 6 Months ago
81

You're using Exceptions for page logic, and I personally think that's not a good thing. Exceptions should be used to signal when bad or unexpected things happen, not to control the output of an error page. If you want to generate an error page based on Exceptions, consider using set_exception_handler. Any uncaught exceptions are run through whatever callback method you specify. Keep in mind that this doesn't stop the "fatalness" of an Exception. After an exception is passed through your callback, execution will stop like normal after any uncaught exception.

Saturday, May 29, 2021
 
Optimus
answered 7 Months ago
62

There are cases where you don't mind that a pattern match is non-exhaustive. For example, while this might not be the optimal implementation, I don't think it would help if it didn't compile:

fac 0 = 1
fac n | n > 0 = n * fac (n-1)

That this is non-exhaustive (negative numbers don't match any case) doesn't really matter for the typical usage of the factorial function.

Also it might not generally be possible to decide for the compiler if a pattern match is exhaustive:

mod2 :: Integer -> Integer
mod2 n | even n = 0
mod2 n | odd n  = 1

Here all cases should be covered, but the compiler probably can't detect it. Since the guards could be arbitrarily complex, the compiler cannot always decide if the patterns are exhaustive. Of course this example would better be written with otherwise, but I think it should also compile in its current form.

Thursday, July 29, 2021
 
MKM
answered 4 Months ago
MKM
23

(a, [(b, c)]) does not match (1, [(2, 3), (4, 5)]), because the list in the latter has two elements while your pattern requires there to be only one.

If you want to leave the list unchanged, use this pattern instead:

foo (a, bar) = (a+1, bar)

Now bar will match [(2, 3), (4, 5)] because it is just a binding which will match anything of the correct type.

Friday, August 27, 2021
 
Fernando
answered 3 Months ago
89

There's no need to throw-and-catch, you can simply call:

new Exception().printStackTrace();

or even easier:

Thread.dumpStack();

You can also get the stack trace from the current thread as an array:

StackTraceElement[] trace = Thread.currentThread().getStackTrace();

If you want to do something more detailed like inspect the stack at runtime (e.g. to get the calling method's name).

Saturday, August 28, 2021
 
Mikita Belahlazau
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share