2011-07-17 244 views
36

我有一個問題。我編寫了一個大型的Haskell程序,它總是以小輸入工作。現在,當我想測試它,併產生更大的投入,我總是得到消息:如何調試Haskell代碼?

HsProg: Prelude.head: empty list 

我用Prelude.head很多次。我能做些什麼來獲得更多的信息或獲得更好的錯誤輸出以獲取發生的代碼行?

+0

什麼interpiter或編譯器使用? – Sudantha

+0

我用的是:GHC 7.0.3 – haskellNewcommer

+0

希望這將幫助你 [如何「調試」哈斯克爾與printfs輸出?] [1] [1]:http://stackoverflow.com/questions/3546592/how-to-debug-haskell-with-printfs – Sudantha

回答

67

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. 

現在,我們打開-fbreak-on-exceptions和跟蹤(在這種情況下,整個程序main)我們的表達。

*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發生的事情,我們不能從源頭上直接看。但是,當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 

在終端中,冒號表達式filter odd [2, 4, 6]以粗體突出顯示。所以這是在這種情況下評估爲空列表的表達式。

有關如何使用GHCi調試器的更多信息,請參閱the GHC User's Guide

+0

輝煌。我沒有找到關於GHCi調試器的信息,但這非常酷。 –

+0

https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci-debugger.html –

+2

-fbreak-on-exception已更改爲-f-on-error。 – holdenlee

9

您可能想看看Haskell Wiki - Debugging,其中包含許多有用的方法來解決您的問題。

一個有希望的工具是LocH,這會幫助你找到你的代碼從而引發了空列表錯誤head調用。

就個人而言,我推薦safe包,這允許從前奏註釋最局部函數(並且因此導致更意識地使用那些部分功能),或者更好的是,使用的功能的變體如head,它總是返回結果(如果輸入值爲,至少定義爲)。

+3

我首先建議不要使用'head',特別是對於新語言的人。 –

+0

@camccann我完全同意......唉,我見過的大多數介紹性材料(包括相當現代的LYAH)都是以解釋「head」開始的,並且只是警告注意不要將它應用於空列表中: -/ – hvr

+0

如果我有*我*的方式,我會從「Prelude」完全刪除它(連同'tail','(!!)'和其他一些東西),而且從來沒有向初學者提及它。但是,好吧。 –