I've been working with parsec and I have trouble debugging my code. For example, I can set a breakpoint in ghci, but I'm not sure how to see how much of the input has been consumed, or things like that.
Are there tools / guidelines to help with debugging parsec code?
You might be able to use the <?>
operator in Text.Parsec.Prim to make better error messages for you and your users. There are some examples in Real World Haskell. If your parser has good sub-parts then you could setup a few simple tests (or use HUnit) to ensure they work separately as expected.
Another useful trick:
_ <- many anyChar >>= fail
this will generate an error (Left
) of:
unexpected end of input
the remaining 'string'
I think the parserTrace
and parserTraced
functions mentioned here http://hackage.haskell.org/package/parsec-3.1.13.0/docs/Text-Parsec-Combinator.html#g:1 do something similar to the above.
This page might help.
Debug.trace
is your friend, it allows you to essentially do some printf
debugging. It evaluates and prints its first argument and then returns its second. So if you have something like
foo :: Show a => a -> a
foo = bar . quux
You can debug the 'value' of foo's parameter by changing foo
to the following:
import Debug.Trace(trace)
foo :: Show a => a -> a
foo x = bar $ quux $ trace ("x is: " ++ show x) x
foo will now work the same way as it did before, but when you call foo 1
it will now print x is: 1
to stderr when evaluated.
For more in-depth debugging, you'll want to use GHCI's debugging commands. Specifically, it sounds like you're looking for the :force
command, which forces the evaluation of a variable and prints it out. (The alternative is the :print
command, which prints as much of the variable as has been evaluated, without evaluating any more.)
Note that :force
is more helpful in figuring out the contents of a variable, but may also change the semantics of your program (if your program depends upon laziness).
A general GHCI debugging workflow looks something like this:
:break
to set breakpoints:list
and :show context
to check where you are in the code:show bindings
to check the variable bindings:print
to see what's currently bound:force
if necessary to check your bindingsIf you're trying to debug an infinite loop, it also helps to use
:set -fbreak-on-error
:trace myLoopingFunc x y
Then you can hit Ctrl-C
during the loop and use :history
to see what's looping.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With