我正在网上浏览一些旧课程并遇到了这个任务:
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
。我已经被困在它上很长时间了,无法绕过它。
非常感谢您的参与。
答案 0 :(得分:1)
正如其名称和类型签名所暗示的那样,foldRT
对于您的树来说是一个真正的正确折叠(您可以通过手工评估它来表达Branch 1 (Branch 0 Leaf Leaf) (Branch 2 Leaf Leaf)
之类的东西。这意味着实施Foldable
将为您提供foldRT
:foldRT = 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的解决方案。)