trace可以给出折叠处理的“反转”

时间:2015-09-19 13:48:32

标签: haskell

当我编译“修改后的总和”(«_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')似乎已被倒置(它是'折叠')......!?

这是什么意思?

1 个答案:

答案 0 :(得分:5)

表达式foldl (+) 0 [1..3]创建以下表达式树:

              +
             / \
            +   3
           / \
          +   2
         / \
        0   1

在您的情况下,_sum_sum2都会构建一个这样的树:

              tr
             / \
            tr  3
           / \
          tr   2
         / \
        0   1

这里tr是折叠中的函数,用于累积 和追踪。

_sum2

要访问的第一个操作是树顶部的tr ___ 3x函数中的3为acc,___为tr

如果在_sum2中发生这种情况,则会打印3。

然后评估acc,因此评估tr ___ 2会导致显示2。

然后评估tr ___ 1,打印1。

_sum

然而,在_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。