当我编译"修改后的总和"(«_sum_folds.hs»)文件时:
*--------------------------- [
import Debug.Trace
_sum =
foldl ( \ acc x ->
trace (
show x
++ " - " ++ show acc
)
acc + x
)
0
*--------------------------- ]
[1 of 1] Compiling Main ( _sum_folds .hs, interpreted )
Ok, modules loaded: Main.
Run Code Online (Sandbox Code Playgroud)
...并将其应用于'[1..5]',我得到:
*Main > _sum ([1..5])
* 1 - 0
* 2 - 1
* 3 - 3
* 4 - 6
* 5 - 10
* 15
* it :: Integer
Run Code Online (Sandbox Code Playgroud)
('foldl'过程的顺序没问题......)
如果我删除<++" - "++ show acc>,我得到:
(我们只有<trace(show x)>)
*Main > _sum ([1..5])
* 5
* 4
* 3
* 2
* 1
* 15
* it :: Integer
Run Code Online (Sandbox Code Playgroud)
...:<[1..5]>('x')内部元素的处理顺序似乎已被反转(它是'foldl')......!
这是什么意思 ?
表达式foldl (+) 0 [1..3]创建以下表达式树:
+
/ \
+ 3
/ \
+ 2
/ \
0 1
Run Code Online (Sandbox Code Playgroud)
在你的情况下,_sum并_sum2建立一个这样的树:
tr
/ \
tr 3
/ \
tr 2
/ \
0 1
Run Code Online (Sandbox Code Playgroud)
这tr是折叠中的功能,用于累积和跟踪.
要访问的第一个操作是tr ___ 3在树的顶部.3是x和___ acc在tr函数中.
当这发生在_sum23打印.
然后acc进行评估,因此tr ___ 2进行评估,结果显示为2.
然后tr ___ 1进行评估,因此打印1.
然而,在_sum不同的事件过程中展开(没有双关语意).
我们再次从树顶开始:tr ___ 3.
步骤1)
因为在_sum你也打印出来acc,Haskell需要评估它,即tr ___ 2.评估完成后,将打印出来acc然后打印3.
步骤2)
为了评估tr ___ 2,因为你打印出来acc,Haskell需要评估它,即2左边的树 - 即tr ___ 1.评估完成后,将打印出来acc然后打印2.
步骤3)
为了评估tr ___ 1,因为你正在打印出来acc,Haskell需要评估1左边的树,即0.当这个评估完成时,它将打印出来acc,然后是1.在这种情况下,0已被评估,所以它打印出0然后打印1.
然后控制转回到步骤2并acc显示(1)然后显示2.
然后控制转回到步骤1并acc显示(3)和3.