2013-05-27 30 views
8

當函數的結果已知時,可以停止GHCi調試器嗎?使用GHCi斷點調試器查找中間結果?

例如,請考慮下面的代碼片段:

blabla :: [Int] -> Int 
bla  :: Int -> Int 
papperlap :: Int -> Int -> Int 

bla x   = x+x 
papperlap y x = ((y *) . bla) x 
blabla xs  = foldl papperlap 0 x 

現在,我想看看「papperlap」和「喇嘛」的結果。但請記住,當評估結果時我想停止。因此,使用':force'是不可能的,因爲它會改變評估順序。

當我使用':break'時,調試器停止,但_result尚未評估。請在下面找到我的GHCi會話,但不會產生所需的中間結果:

GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
[1 of 1] Compiling Main    (bla1.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> :break blabla 
Breakpoint 0 activated at bla1.hs:7:1-36 
*Main> :break papperlap 
Breakpoint 1 activated at bla1.hs:6:1-31 
*Main> :break bla 
Breakpoint 2 activated at bla1.hs:5:1-19 
*Main> blabla [1,2,3] 
Stopped at bla1.hs:7:1-36 
_result :: Int = _ 
[bla1.hs:7:1-36] *Main> :step 
Stopped at bla1.hs:7:17-36 
_result :: Int = _ 
xs :: [Int] = [1,2,3] 
[bla1.hs:7:17-36] *Main> :step 
Stopped at bla1.hs:6:1-31 
_result :: Int = _ 
[bla1.hs:6:1-31] *Main> :step 
Stopped at bla1.hs:6:17-31 
_result :: Int = _ 
x :: Int = 3 
y :: Int = _ 
[bla1.hs:6:17-31] *Main> :step 
Stopped at bla1.hs:6:1-31 
_result :: Int = _ 
[bla1.hs:6:1-31] *Main> :step 
Stopped at bla1.hs:6:17-31 
_result :: Int = _ 
x :: Int = 2 
y :: Int = _ 
[bla1.hs:6:17-31] *Main> :step 
Stopped at bla1.hs:6:1-31 
_result :: Int = _ 
[bla1.hs:6:1-31] *Main> :step 
Stopped at bla1.hs:6:17-31 
_result :: Int = _ 
x :: Int = 1 
y :: Int = 0 
[bla1.hs:6:17-31] *Main> :step 
Stopped at bla1.hs:5:1-19 
_result :: Int = _ 
[bla1.hs:5:1-19] *Main> :step 
Stopped at bla1.hs:5:17-19 
_result :: Int = _ 
x :: Int = 1 
[bla1.hs:5:17-19] *Main> :step 
Stopped at bla1.hs:5:1-19 
_result :: Int = _ 
[bla1.hs:5:1-19] *Main> :step 
Stopped at bla1.hs:5:17-19 
_result :: Int = _ 
x :: Int = 2 
[bla1.hs:5:17-19] *Main> :step 
Stopped at bla1.hs:5:1-19 
_result :: Int = _ 
[bla1.hs:5:1-19] *Main> :step 
Stopped at bla1.hs:5:17-19 
_result :: Int = _ 
x :: Int = 3 
[bla1.hs:5:17-19] *Main> :step 
0 
*Main> 

回答

0

Haskell不會爲您逐句通過文字表達式。像

e = 2*(2+2) 

東西會立即評估〜8,因爲編譯器優化任何文字它可以找到在編譯時只是「周圍鋪設」組成的表達式(這種類型的表達的被稱爲恆定應用形式)。

現在你必須認識到foldl是懶惰的。如果您在列表中呼叫foldl f,它將不會執行f的單個評估,直到完全被迫這樣做。

>foldl (+) 0 [1,2,3] 
>foldl (+) a1 [2,3] 
    where a1 = 0+1 
>foldl (+) a2 [3] 
    where a2 = a1+2 
      where a1 = 0+1 

最終我們有((0+1)+2)+3)和編譯器說:「好了,我們已經用盡一切列表,每一個評估擴展到我們可以最原始的形式,讓評估」。而且我們已經知道Haskell 不會通過逐步評估CAF。

如果您想查看評估的中間值,您必須首先實際生成評估值。你做的方式是foldl以下嚴格的變種:

foldl' f z []  = z 
foldl' f z (x:xs) = let z' = z `f` x 
        in seq z' $ foldl' f z' xs 

我會離開你要弄清楚它是如何工作的,但seq a b將全力evalutate a繼續延遲計算b之前。

除了將foldl更改爲foldl'之外,其他都和以前一樣。當您逐步完成評估時,您將在foldl'函數內暫停時看到中間值。

+0

謝謝你的回答。然而,切換到嚴格的評估並不是我想要的,在這種情況下,我也可以使用':force'。 我的意圖是能夠檢查'bla'和'papperlap'的結果,當它們的結果值被評估時。 並以abtain類似的結果: 'BLA 1 = 2; papperlap 0 1 = 0; bla 2 = 4; papperlap 0 2 = 0; bla 3 = 6; papperlap 0 3 = 0; blabla [1,2,3] = 0' –

3

可能是有點晚了你的眼前調試的擔憂,但這裏是我會做:

blabla :: [Int] -> Int 
bla  :: Int -> Int 
papperlap :: Int -> Int -> Int 

bla x   = (undefined :: Int) 
papperlap y x = ((y *) . bla) x 
blabla xs = foldl papperlap 0 xs 

現在我們知道我們會在bla評價得到一個異常。因此,讓我們落入ghci的:

[1 of 1] Compiling Main    (temp.hs, interpreted) 
Ok, modules loaded: Main. 
λ: :set -fbreak-on-exception 
λ: :trace blabla [1,5,17] 
Stopped at <exception thrown> 
_exception :: e = _ 
λ: :hist 
-1 : bla (temp.hs:6:17-35) 
-2 : bla (temp.hs:6:1-35) 
-3 : papperlap (temp.hs:7:17-31) 
-4 : papperlap (temp.hs:7:1-31) 
-5 : papperlap (temp.hs:7:17-31) 
-6 : papperlap (temp.hs:7:1-31) 
-7 : papperlap (temp.hs:7:17-31) 
-8 : papperlap (temp.hs:7:1-31) 
-9 : blabla (temp.hs:8:13-32) 
-10 : blabla (temp.hs:8:1-32) 
<end of history> 
λ: :back 
Logged breakpoint at temp.hs:6:17-35 
_result :: a 
λ: :list 
5 
6 bla x   = (undefined :: Int) 
        ^^^^^^^^^^^^^^^^^^^ 
7 papperlap y x = ((y *) . bla) x 
λ: :back 
Logged breakpoint at temp.hs:6:1-35 
_result :: a 
λ: :list 
5 
6 bla x   = (undefined :: Int) 
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
7 papperlap y x = ((y *) . bla) x 
λ: :back 
Logged breakpoint at temp.hs:7:17-31 
_result :: Int 
x :: Int 
y :: Int 
λ: :list 
6 bla x   = (undefined :: Int) 
7 papperlap y x = ((y *) . bla) x 
        ^^^^^^^^^^^^^^^ 
8 blabla xs = foldl papperlap 0 xs 

因此,我們可以看到堆棧導致高達bla右手邊的評價。

這是不完美的,因爲投入undefined到處都是,似乎俗氣和哈克,但:hist爲您提供了相當多的已經工作,並使用:list你退後一步使事情變得更加清晰。