尝试使用有序遍历在Haskell中展平一棵树

时间:2018-09-21 05:51:45

标签: haskell functional-programming binary-tree

尝试使用给定的fold函数将一棵树展平为一个列表。

treeFold :: (b -> a -> b -> b) -> b -> Tree a -> b
treeFold _ b Leaf         = b
treeFold f b (Node lt x rt) = f (treeFold f b lt) x (treeFold f b rt)

这是我到目前为止想要尝试的:

treeToList :: Tree a -> [a]
treeToList = treeFold (\xs x ys -> xs ++ x : ys) (\x -> [x])

由于某种原因,我无法完全理解如何进行此操作? 感觉有些关于Haskell的事情我还不太了解。任何帮助将不胜感激以及如何去解决它。 谢谢!

编辑:

我意识到我在这里使用的类型签名完全是荒谬的。根据我的想法,在treeFold的类型签名中,第二个参数(b)可能是一个列表,因为在这种情况下它以某种方式充当累加器。这将使第三个参数(树a)成为等式左侧参数的某种形式。函数中的两个参数必须是Node中的左子树和右子树。第三个参数只是Node的值。在该函数中,我需要按顺序将左树,右树和值以常规方式组合在一起,但是我尝试过的所有不同变体都存在一些问题

2 个答案:

答案 0 :(得分:4)

treeFold的类型是

treeFold :: (b -> a -> b -> b) -> b -> Tree a -> b

您要返回值列表[a]

因此,结果类型b必须等于[a],为我们提供了专门的类型签名

treeFold :: ([a] -> a -> [a] -> [a]) -> [a] -> Tree a -> [a]

请注意,第二个参数的类型为[a]

您传递的是什么价值?

答案 1 :(得分:4)

类型必须适合:

treeFold ::           ( b -> a -> b -> b              ) -> b -> Tree a -> b

treeToList = treeFold (\xs   x    ys -> xs ++ (x : ys))    z
-------------------------------------------------------------------
                        b    a    b     b      a   b       b
                                              --------
                                              b

由于xys参与相同的:,因此它们的类型必须兼容:

(:) ::   a  -> [a]  ->  [a]
x   ::   a
ys  ::          b
-------------------
              b ~ [a]

因此我们有

treeFold ::           ( [a] -> a -> [a] -> [a]           ) -> [a] -> Tree a->[a]

treeToList = treeFold (\ xs    x    ys  -> xs ++ (x : ys))     z
-------------------------------------------------------------------
                         [a]   a    [a]    [a]    a   [a]     [a]
                                                 --------
                                                 [a]

结论:最后一个参数z必须具有类型[a]

此参数的含义是什么?与折叠一样,数据类型定义中的每个“变体”都有一个对应于fold函数的参数。

(丢失的)数据类型定义是:

data Tree a = Node (Tree a)    a   (Tree a)       | Leaf

折叠的类型是

treeFold ::   (         b  ->  a  ->  b  -> b )   ->  b     -> Tree a -> b

对应于

的“ 递归结果保持类型”

data TreeF a r = NodeF  r      a      r           | LeafF

因此,z是“将每个Leaf转换为的值”。

最自然的选择就是[]。实际上,这是唯一的选择,因为我们对a(在[a]中)的类型一无所知。