如何debuggingHaskell代码?

我有个问题。 我写了一个大的Haskell程序,它总是以小的input工作。 现在,当我想testing它并产生更大的input时,我总是得到这样的信息:

HsProg: Prelude.head: empty list 

我多次使用Prelude.head 。 我能做些什么来获得更多的信息或者获得更好的错误输出来获取发生的代码行?

GHCi选项-fbreak-on-exception可以是有用的。 这里是一个debugging会话的例子。 首先我们把我们的文件加载到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. 

现在,我们打开-fbreak-on-exceptions并跟踪我们的expression式(在这个例子中是整个程序的主要部分)。

 *Main> :set -fbreak-on-exception *Main> :trace main Stopped at <exception thrown> _exception :: e = _ 

我们已经停止了一个例外。 我们来看看代码:list

 [<exception thrown>] *Main> :list Unable to list source for <exception thrown> Try :back then :list 

由于Prelude.head发生exception,我们不能直接查看源代码。 但是,如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 

在terminal中,有问题的expression式filter odd [2, 4, 6]以粗体突出显示。 所以这是在这种情况下评估为空列表的expression式。

有关如何使用GHCidebugging器的更多信息,请参阅GHC用户指南 。

您可能想看看Haskell Wiki – debugging ,其中包含许多有用的方法来解决您的问题。

一个有前途的工具是LocH ,它可以帮助你在代码中定位head调用,从而触发空列表错误。

就我个人而言,我推荐安全包,它允许从Prelude中注释大部分的部分function(从而导致更有意识地使用这些部分function),或者更好地使用总是返回结果的head (如果input值至less被定义 )。