使用有序遍历展平haskell中的树

时间:2016-11-08 15:24:36

标签: haskell functional-programming inorder

我想使用我定义的foldTree函数和按顺序遍历来实现展平树。在展平后应该返回一个列表。

data Tree t = Leaf t
        | Tree (Tree t) t (Tree t)


foldTree :: (t1 -> t -> t1 -> t1) -> (t -> t1) -> Tree t -> t1
foldTree treeFn leafFn tree =
case tree of
  Leaf v -> leafFn v
  Tree leftTree q rightTree -> treeFn (foldTree treeFn leafFn leftTree) q (foldTree treeFn leafFn rightTree)


Input : foldTree (\t1 t t2->t1 + 5*t + t2) (\x->x+9) (Leaf 5)
Expected Output : 14

Input : foldTree (\t1 t t2->t1 + 3*t + t2) (\x->x+5) (Tree (Leaf 3) 2 (Leaf 4))
Expected Output : 23

我尝试了以下代码,但它使用了递归。我想从flattenTree调用foldTree来实现树的扁平化,而不是对flatTree进行递归调用。(在flattenTree中使用foldTree函数)。任何人都可以帮助我如何整合它。

flatTree :: Tree a -> [a]
flatTree tree = 
case tree of
    Leaf v -> [v]
    Tree p v r -> (flatTree p) ++ [v] ++ (flatTree r) 

Input: flatTree (Tree (Leaf 5) 3 (Tree (Leaf 3) 2 (Leaf 4)))
Expected output : [5,3,3,2,4]

1 个答案:

答案 0 :(得分:2)

查看foldTree的类型。

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

您可以看到b是catamorphism的结果类型。 foldTree通过折叠每个子树来获得每个子树的结果b,然后使用折叠函数组合它们。

由于您希望结果是树的元素的展平列表,所以我们设置b ~ [a]

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

因此foldTree的第二个参数应该是将单个元素a注入到列表[a]中的内容,第一个应该是将两个列表与要生成的元素组合在一起的内容更大的清单。

flatTree = foldTree (\xs x ys -> xs ++ x : ys) (\x -> [x])

顺便说一句,GHC只需查看类型的结构,就可以为您编写flatTree函数。 flatTree :: Tree a -> [a]匹配toList :: Foldable f => f a -> [a]的类型,here类是Foldable类的一部分。您需要做的只是说出神奇的单词deriving Foldable,而GHC会吐出Foldable的实例。

{-# LANGUAGE DeriveFoldable #-}

data Tree t = Leaf t
            | Tree (Tree t) t (Tree t)
            deriving Foldable

flatTree :: Tree a -> [a]
flatTree = toList

由于Tree构造函数的布局方式,toList将执行有序遍历。这可以通过调整Tree构造函数的定义来改变。