Maa*_*gon 9 debugging haskell lazy-evaluation
当函数的结果已知时,是否可以停止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
Run Code Online (Sandbox Code Playgroud)
现在,我想看看'papperlap'和'bla'的结果.但请记住,我想在评估结果时停止.因此,使用':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>
Run Code Online (Sandbox Code Playgroud)
Haskell 不会为您单步执行文字表达式。就像是
e = 2*(2+2)
Run Code Online (Sandbox Code Playgroud)
将立即计算为 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
Run Code Online (Sandbox Code Playgroud)
最终我们得到了((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
Run Code Online (Sandbox Code Playgroud)
我会让你弄清楚它是如何工作的,但会在继续懒惰地评估之前进行seq a b全面评估。ab
像以前一样执行其他所有操作,除了更改foldl为foldl'. 当您逐步执行评估时,当您在函数内暂停时,您将看到中间内容foldl'。
| 归档时间: |
|
| 查看次数: |
2892 次 |
| 最近记录: |