当我编译“修改后的总和”(«_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.
...并将其应用于'[1..5]',我得到:
*Main > _sum ([1..5])
* 1 - 0
* 2 - 1
* 3 - 3
* 4 - 6
* 5 - 10
* 15
* it :: Integer
('foldl'过程的顺序没问题......)
如果我删除< ++“ - ”++ show acc> , 我明白了:
(我们只有< trace(show x)>)
*Main > _sum ([1..5])
* 5
* 4
* 3
* 2
* 1
* 15
* it :: Integer
...:里面元素的处理顺序< [1..5]> ('x')似乎已被倒置(它是'折叠')......!?
这是什么意思?
答案 0 :(得分:5)
表达式foldl (+) 0 [1..3]
创建以下表达式树:
+
/ \
+ 3
/ \
+ 2
/ \
0 1
在您的情况下,_sum
和_sum2
都会构建一个这样的树:
tr
/ \
tr 3
/ \
tr 2
/ \
0 1
这里tr
是折叠中的函数,用于累积
和追踪。
要访问的第一个操作是树顶部的tr ___ 3
。
x
函数中的3为acc
,___为tr
。
如果在_sum2
中发生这种情况,则会打印3。
然后评估acc
,因此评估tr ___ 2
会导致显示2。
然后评估tr ___ 1
,打印1。
然而,在_sum
中,不同的事件过程展开(没有双关语意)。
我们再次从树的顶部开始:tr ___ 3
。
步骤1)
因为在_sum
中你也打印出acc
,所以Haskell需要
评估它,即tr ___ 2
。
评估完成后,将打印出acc
然后打印出来。
第2步)
要评估tr ___ 2
,因为要打印出acc
,Haskell需要对其进行评估,即2左侧的树 - 即tr ___ 1
。
评估完成后,将打印出acc
,然后打印出2.
第3步)
要评估tr ___ 1
,因为要打印出acc
,Haskell需要评估1左边的树,即0。
评估完成后,将打印出acc
,然后打印出1。
在这种情况下,0已经被评估,因此它打印出0然后是1。
然后控制转回第2步,显示{1},然后显示{。}}。
然后控制转回第1步,显示acc
(3)和3。