【问题标题】:Creating a Custom Fold Function for Custom Tree为自定义树创建自定义折叠函数
【发布时间】:2017-03-30 23:50:41
【问题描述】:

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

我的树很简单:

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

如何更新第二行(或方法中的其他内容以使其正常工作?

感谢您的帮助!

【问题讨论】:

  • 折叠将重复地将给定函数应用于单个元素,之前的结果作为输入之一。这将有一个顺序,它基本上将您的结构变成一个平面序列。想想你想如何为你的数据结构做这件事。您想以什么顺序应用该功能?基本上我要问的是你怎么能把Stem a变成[a]?此时您不需要编写自己的折叠,您可以使用内置的列表。
  • 我知道我可以使用内置的,但我正在阅读的书建议我尝试其中一个练习,所以我知道这是可能的,但我很难弄清楚。 (不幸的是,它没有提供这个答案)
  • (x -&gt; u -&gt; u) 对我来说看起来不对,你确定你不想要 (x -&gt; x -&gt; u) 吗?我希望这样:foldTree :: (x -&gt; x -&gt; u) -&gt; (x -&gt; u) -&gt; Stem x -&gt; u
  • 对不起,chi,但我不明白你是如何得出这个结论的,你介意解释一下你是如何/为什么这么认为的吗?
  • 此问题现已作为重复问题关闭,但重复问题中的树使用不同的树类型(数据位于内部节点而不是叶子中)。这里稍微改变了fold函数的类型,但是解决的本质是一样的。

标签: haskell fold


【解决方案1】:

首先处理简单的具体案例,然后将逻辑扩展到一般案例。 Leaf

foldTree f a (Leaf o) = f o a

然后想想你想在只有两个Leafs 的Node 的情况下发生什么:

foldTree f a (Node (Leaf x) (Leaf y)) = _

这里我们知道f 必须被应用两次,但顺序是什么?让我们从Node 的第一个槽中的Leaf 开始:

foldTree f a (Node (Leaf x) (Leaf y)) = _ (f x a)

我在表达式中留下了漏洞 (_),因为当您尝试编译时,GHC 实际上会告诉您需要什么类型的东西去那里。在这种情况下,它会说你需要u -&gt; u 类型的东西,因为f x a :: u。好吧,我们知道f :: x -&gt; u -&gt; 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 afoldTree 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

整个定义是

foldTree f a (Leaf x) = f x a
foldTree f a (Node left right) = foldTree f (foldTree f a left) right

【讨论】:

  • 仔细检查您的从左到右方向。问题请求foldr。此解决方案既不提供foldl 也不提供foldr。但是编辑距离很小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
相关资源
最近更新 更多