自上而下的递归方案

时间:2019-09-03 17:37:46

标签: haskell recursion order-of-execution recursion-schemes

我们是否可以定义一种递归方案(而不失去其通用性),以 构造自顶向下的值 ,而不是自底向上?

这将非常有帮助,因为我已经看到很多次使用递归方案在内部定义的函数首先将reverse应用于其输入,从而明确表明需要foldl-例如“从前到后”执行。

1 个答案:

答案 0 :(得分:11)

尽管普遍认为cata是“自下而上”的,但实际上它可以通过使用参数为函数的载体实例化载体来表示“自上而下”的构造,该函数的参数是要传递的信息“自上而下”下”:

cata :: (F  c       ->  c      ) -> Fix F -> c       -- general signature
     :: (F (i -> d) -> (i -> d)) -> Fix F -> i -> d  -- with  c = (i -> d)

这就是使用foldl(列表的reverse)来实现foldrcata的方式。

--   foldl :: (b -> a -> b) -> b -> [a] -> b
-- using
--   foldr :: (a -> (b -> b) -> (b -> b)) -> (b -> b) -> [a] -> b -> b

foldl f b xs = foldr (\x go z -> go (f z x)) id xs b

这是另一个从根数开始按深度标记树的示例:

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

makeBaseFunctor ''Tree  -- recursion-schemes

byDepth :: Tree a -> Tree Integer
byDepth t = cata byDepthF t 0 where
  byDepthF :: TreeF a (Integer -> Tree Integer) -> Integer -> Tree Integer
  byDepthF (NodeF u _ v) !d = Node (u (d + 1)) d (v (d + 1))
  byDepthF LeafF = Leaf