为自定义树

时间:2017-03-30 13:50:51

标签: haskell fold

我正在尝试创建自己的折叠函数,然后我可以在自定义树上使用它。

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

如何更新第二行(或者可能是方法中的其他内容以使其起作用?

感谢您的帮助!

1 个答案:

答案 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