2013-05-27 7 views
8

関数の結果が分かっているときにGHCiデバッガを停止することはできますか?私は「papperlap」と「BLA」の結果を確認したいと思い、今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 

は例えば、次のコードスニペットを考えてみましょう。しかし、私は結果が評価されるときに止めたいと思います。したがって、 ':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の1回の評価は実行されません。

>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)を持っていると、コンパイラは「OK、我々はすべてのリストを使い果たし、私たちができる最も原始的な形にすべての評価を拡大してきた。評価できます」と言います。そして我々はすでに、ハスケルは、 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

ありがとうございました。しかし、厳密な評価に切り替えることは、私が望むものではなく、その場合は「:力」を使うこともできます。 「bla」と「papperlap」の結果値を評価した結果を調べることができます。 同様の結果を得るには 'bla 1 = 2; パープルラップ0 1 = 0; bla2 = 4; パープルラップ0 2 = 0; 、bla3 = 6; パープルラップ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の評価に例外を取得します知っています。

[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の右手側の評価に至るまでのスタックを見ることができます:それでは、GHCiのにドロップしてみましょう。どこにでも粘着性とハックようだundefined Sに入れているので

これは、完璧ではないですが、:histは、すでに上で動作するためにあなたにかなりを与え、あなたは物事がより明確になり、バックステップとして:listを使用します。

関連する問題