我正在尝试创建自己的折叠函数,然后我可以在自定义树上使用它。
My Tree很简单:
data Stem a = Node (Stem a) (Stem a) | Leaf a
我希望能够构建foldTree
函数,其功能与foldr
相同。
我已设法让n=1
或仅leaf
使用以下内容
foldTree :: (x -> u -> u) -> u -> Stem x -> u
foldTree f a (Leaf o) = f o a
但我似乎无法解决下一行(当有节点和叶子的时候IE浏览器),我知道我需要递归调用foldTree,但我不知道我该怎么做。我尝试过以下但我运气不好。
foldTree f a (Node l r) = f a (foldTree f a l) (foldTree f a r)
这不起作用,因为我知道我的参数是x -> u -> u
,所以我有一个太多的参数。虽然这是我被困住的地方,但我不确定如何正确地遍历这两条路径。
所以我一起
foldTree :: (x -> u -> u) -> u -> Stem x -> u
foldTree f a (Leaf o) = f o a
foldTree f a (Node l r) = f a (foldTree f a l) (foldTree f a r) <-- Not working
如何更新第二行(或者可能是方法中的其他内容以使其起作用?
感谢您的帮助!
答案 0 :(得分:2)
首先处理简单的特定情况,然后将逻辑扩展到一般情况。对于Leaf
:
foldTree f a (Leaf o) = f o a
然后考虑一下只有两个Node
的{{1}}你想要发生什么:
Leaf
我们知道foldTree f a (Node (Leaf x) (Leaf y)) = _
必须应用两次,但顺序是什么?让我们从f
的第一个广告位中的Leaf
开始:
Node
我在表达式中留下了洞(foldTree f a (Node (Leaf x) (Leaf y)) = _ (f x a)
)因为GHC实际上会告诉你在尝试编译时需要去哪种类型的东西。在这种情况下,从_
开始,您需要u -> u
类型的内容。好吧,我们知道f x a :: u
,所以我们可以写
f :: x -> u -> u
现在唯一可以填补这个漏洞的是foldTree f a (Node (Leaf x) (Leaf y)) = f _ (f x a)
来自右边的叶子,所以
y
但我们知道foldTree f a (Node (Leaf x) (Leaf y)) = f y (f x a)
与f x a
相同,因此我们可以将其替换为:
foldTree f a (Leaf x)
然后用一个变量替换foldTree f a (Node (Leaf x) (Leaf y)) = f y (foldTree f a (Leaf x))
:
Leaf x
如果你眯着眼睛仔细观察,你会第二次看到同样的模式。只需快速替换
foldTree f a (Node left (Leaf y)) = f y (foldTree f a left)
现在你可以进行替换
foldTree f a (Node left (Leaf y)) = f y a'
where a' = foldTree f a left
整个定义是
foldTree f a (Node left right) = foldTree f a' right
where a' = foldTree f a left