如何调试Haskell代码?

has*_*mer 39 debugging haskell

我有个问题.我写了一个很大的Haskell程序,它始终适用于小输入.现在,当我想测试它并生成更大的输入时,我总是收到消息:

HsProg: Prelude.head: empty list
Run Code Online (Sandbox Code Playgroud)

我用过Prelude.head很多次了.我该怎么做才能找到更多或获得更好的错误输出以获得它发生的代码行?

ham*_*mar 71

GHCi选项-fbreak-on-exception很有用.这是一个调试会话示例.首先,我们将文件加载到GHCi中.

$ ghci Broken.hs
GHCi, version 7.0.2: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
[1 of 1] Compiling Main             ( Broken.hs, interpreted )
Ok, modules loaded: Main.
Run Code Online (Sandbox Code Playgroud)

现在,我们打开-fbreak-on-exceptions并跟踪我们的表达式(main在本例中为整个程序).

*Main> :set -fbreak-on-exception
*Main> :trace main
Stopped at <exception thrown>
_exception :: e = _
Run Code Online (Sandbox Code Playgroud)

我们已经停止了例外.让我们试着看看代码:list.

[<exception thrown>] *Main> :list
Unable to list source for <exception thrown>
Try :back then :list
Run Code Online (Sandbox Code Playgroud)

因为发生了异常Prelude.head,我们无法直接查看源代码.但是,正如GHCi告诉我们的那样,我们可以:back尝试列出之前发生的事情.

[<exception thrown>] *Main> :back
Logged breakpoint at Broken.hs:2:23-42
_result :: [Integer]
[-1: Broken.hs:2:23-42] *Main> :list
1  
2  main = print $ head $ filter odd [2, 4, 6]
3  
Run Code Online (Sandbox Code Playgroud)

在终端中,违规表达式filter odd [2, 4, 6]以粗体突出显示.所以这是在这种情况下计算到空列表的表达式.

有关如何使用GHCi调试器的更多信息,请参阅GHC用户指南.

  • -fbreak-on-exception已更改为-fbreak-on-error. (3认同)

hvr*_*hvr 9

您可能想看看Haskell Wiki - Debugging,它包含许多有用的方法来解决您的问题.

一个有前途的工具是LocH,它可以帮助您head在代码中找到触发空列表错误的调用.

就个人而言,我推荐使用安全包,它允许从Prelude中注释大多数部分函数(从而导致更有意识地使用这些部分函数)或者更好的是,使用函数的变量,例如head总是返回结果(如果至少定义了输入值).

  • 我首先建议不要使用`head`,尤其是那些刚学语言的人. (3认同)
  • 你的 LocH 链接给了我一个 403 错误,但我认为 http://hackage.haskell.org/package/loch 是同一个工具? (2认同)