我对编写递归代码的高阶方式(递归方案)感兴趣,其中递归调用之间可能存在依赖关系。
作为一个简化的例子,考虑一个遍历整数树的函数,检查总和是否小于某个值。我们可以对整棵树求和,并将其与最大值进行比较。或者,我们可以在超过最大值后立即保持运行总和并短路:
data Tree = Leaf Nat | Node Tree Tree
sumLT :: Nat -> Tree -> Bool
sumLT max t = sumLT' max t > 0
sumLT' :: Nat -> Tree -> Int
sumLT' max (Leaf n) = max - n
sumLT' max (Node l r) =
let max' = sumLT' max l
in if max' > 0 then sumLT' max' r else 0
有没有办法用递归方案来表达这个想法——本质上是一个有序的遍历?我对尽可能一般地编写这样的有序遍历感兴趣。
理想情况下,我想要某种方式来编写遍历,其中在数据结构上折叠(或展开)的函数决定了遍历的顺序。无论我最终得到什么抽象,我都希望能够编写sumLT'
上面遍历的逆序版本,而不是从右到左:
sumLT'' :: Nat -> Tree -> Int
sumLT'' max (Leaf n) = max - n
sumLT'' max (Node l r) =
let max' = sumLT'' max r
in if max' > 0 then sumLT'' max' l else 0