折叠树函数在Haskell中如何工作

时间:2019-03-11 20:26:06

标签: haskell tree fold

在这里,我试图理解此功能,它将一棵树折叠为一个值。它显示foldTree接受两个函数作为参数,将第一个函数应用于Tree a的元素,然后将结果传递给第二个函数(b->b->b),后者再次执行某些操作并产生最终结果。

foldTree :: (a -> b) -> (b -> b -> b) -> Tree a -> b
foldTree f g (Leaf x) = f x
foldTree f g (Node tl tr) = g (foldTree f g tl) (foldTree f g tr) 

我正在尝试跟踪输入以查看其工作原理。

Input 1:  foldTree (*2) (\x y -> x + y) (Leaf 6)
Input 2:  foldTree (*2) (\x y -> x + y) (Node (Node (Leaf 1) (Leaf 2)) (Leaf 4))

返回

Output 1 : 12
Output 2 : 14

我要理解的问题是在哪里执行第二个函数参数操作?以及它实际上如何将值传递给第二个函数,显然第二个函数将两个值作为参数,但第一个函数仅返回一个值...从第二个值传递的地方开始?我可以说它是第一个函数两次的结果,所以xy的值是相同的吗?因为第二个函数(\x y -> x + y)接受两个参数?但是结果将与输出1和2中提到的结果不同。

其次,它执行第二个功能后返回最终结果,或者仅应用第一个功能后返回结果,因为我很困惑,即使我删除了第二个功能,它也会产生相同的结果。

第三,g在两个花括号之外的用途是什么? ***g*** (foldTree f g tl) (foldTree f g tr)从一开始就将其视为数据构造函数还是什么?我知道数据构造函数可以构造为智能构造函数,但是在这里它是如何处理的。

我对此感到很困惑,这可能会使我复杂化很多概念吗?请不要犹豫,进入细节。

1 个答案:

答案 0 :(得分:3)

要了解foldTree f g tree的结果,可以使用以下技术:

  • 使用构造函数来写下tree的值,例如在您的示例中,我们有(Node (Node (Leaf 1) (Leaf 2)) (Leaf 4))
  • 在语法上将Leaf替换为f,将Node替换为g。对于前面的示例,我们得到(g (g (f 1) (f 2)) (f 4))
  • 使用函数fg的定义来计算最后一个表达式的结果。例如,我们得到((+) ((+) ((*2) 1) ((*2) 2)) ((*2) 4)) ((+) ((+) (1*2) (2*2)) (4*2))((1*2) + (2*2)) + (4*2),即(2+4)+8 = 14

请注意,我们如何将Leaf的一元构造函数替换为一元函数f,并将Node的二进制构造函数替换为二进制函数g。因此,对于我们的函数,我们总是有正确数量的参数。一般而言,类型会很好匹配。