哈斯克尔:折叠在树上

时间:2018-04-11 01:36:22

标签: haskell

我正在网上浏览一些旧课程并遇到了这个任务:

data Tree a = Leaf 
            | Branch a (Tree a) (Tree a) 
            deriving (Show, Eq)

fold :: (a -> b -> b -> b) -> b -> Tree a -> b
fold _ acc Leaf           = acc
fold f acc (Branch v l r) = f v (fold f acc l) (fold f acc r)

foldRT :: (a -> b -> b) -> b -> Tree a -> b
foldRT _ acc Leaf = acc
foldRT f acc (Branch v l r) = foldRT f (f v (foldRT f acc r)) l

任务是根据foldRT重写fold。我已经被困在它上很长时间了,无法绕过它。

非常感谢您的参与。

1 个答案:

答案 0 :(得分:1)

正如其名称和类型签名所暗示的那样,foldRT对于您的树来说是一个真正的正确折叠(您可以通过手工评估它来表达Branch 1 (Branch 0 Leaf Leaf) (Branch 2 Leaf Leaf)之类的东西。这意味着实施Foldable将为您提供foldRTfoldRT = foldr。为什么这有关系?因为在这种情况下,实现foldMap要比直接编写foldr更容易:

-- Note that l and r here aren't the subtrees, but the results of folding them.
instance Foldable Tree where
    foldMap f = fold (\v l r -> l <> f v <> r) mempty

如果您想在不依赖foldRT实例的情况下撰写Foldable,您只需要扩展基于foldMap的{​​{1}}定义(请参阅{的答案) {3}}我将在这里详细介绍细节:

foldr

(请注意,我们最终只通过间接路线达到了排序this question的解决方案。)

相关问题