假设我们定义了一个Rose Tree,以及相应的数据类型的折叠。
data RTree a = Node a [RTree a]
foldRTree :: (a -> [b] -> b) -> RTree a -> b
foldRTree f (Node x xs) = f x (map (foldRTree f) xs)
这种结构的深度优先遍历的递归定义是:
dft :: RTree a -> [a]
dft (Node x xs) = x : concat (map dft xs)
我们可以将dft表示为玫瑰树的折叠,特别是我们可以代数地得出这样的折叠。
// Suppose dft = foldRTree f
// Then foldRTree f (Node x xs) = f x (map (foldRTree f) xs) (definition of foldRTree)
// But also foldRTree f (Node x xs) = dft (Node x xs) (by assumption)
// = x : concat (map dft xs) (definition of dft)
// So we deduce that f x (map (foldRTree f) xs) = x : concat (map dft xs)
// Hence f x (map dft xs) = x : concat (map dft xs) (by assumption)
// So we now see that f x y = x : concat y
我想我们可以这样做的原因是因为foldRTree捕获了RTree上的一般递归结构,这使我得到了关于展开的查询。
我们定义展开如下:
unfold :: (a -> Bool) -> (a -> b) -> (a -> a) -> a -> [b]
unfold n h t x | n x = []
| otherwise = h x : unfold n h t (t x)
// Or Equivalently
unfold' n h t = map h . takeWhile (not.n) . iterate t
我们可以将深度第一次遍历表达为如下展开:
dft (Node x xs) = x : unfold null h t xs
where h ((Node a xs) : ys) = a
t ((Node a xs) : ys) = xs ++ ys
我正在努力找到一种方法来开发一种代数计算函数的方法,与cons一样。特别是在开发展开方面有一个巧妙的步骤,即要意识到展开的最终论证需要是[RTree a]而不仅仅是RTree a。因此,对dft提出的论证并未直接传递到展开,因此我们在推理这两个函数方面遇到了障碍。
我非常感谢任何能够以这样的方式提供推理的数学推理方法来计算所需的函数nh,以及当表达递归函数(自然是折叠)作为展开时(或许)使用一些连接折叠和展开的法律?)。那么一个自然的问题就是我们必须用什么方法证明这种关系是正确的。