我一直在使用 parsec,但在调试代码时遇到了麻烦。例如,我可以在 ghci 中设置断点,但我不确定如何查看消耗了多少输入,或者类似的东西。
是否有工具/指南可以帮助调试 parsec 代码?
此页面可能会有所帮助。
Debug.trace
是您的朋友,它允许您从本质上进行一些printf
调试。它计算并打印它的第一个参数,然后返回它的第二个。所以如果你有类似的东西
foo :: Show a => a -> a
foo = bar . quux
foo
您可以通过更改为以下内容来调试 foo 参数的“值” :
import Debug.Trace(trace)
foo :: Show a => a -> a
foo x = bar $ quux $ trace ("x is: " ++ show x) x
foo 现在将像以前一样工作,但是当你调用foo 1
它时,它现在会在评估时打印x is: 1
到 stderr。
要进行更深入的调试,您需要使用 GHCI 的调试命令。具体来说,听起来您正在寻找:force
命令,该命令会强制评估变量并将其打印出来。(替代方法是:print
命令,它打印已评估的尽可能多的变量,不再评估。)
请注意,这:force
对找出变量的内容更有帮助,但也可能会改变程序的语义(如果您的程序依赖于惰性)。
一般的 GHCI 调试工作流程如下所示:
:break
设置断点:list
and:show context
检查您在代码中的位置:show bindings
检查变量绑定:print
查看当前绑定的内容:force
如有必要,请使用检查您的绑定如果您正在尝试调试无限循环,它也有助于使用
:set -fbreak-on-error
:trace myLoopingFunc x y
然后你可以Ctrl-C
在循环中点击并使用:history
来查看循环的内容。
另一个有用的技巧:
_ <- many anyChar >>= fail
这将产生一个错误(Left
):
unexpected end of input
the remaining 'string'
我认为这里提到的parserTrace
和parserTraced
函数http://hackage.haskell.org/package/parsec-3.1.13.0/docs/Text-Parsec-Combinator.html#g:1做类似于上面的事情。