【发布时间】:2018-05-14 07:45:08
【问题描述】:
我想要一些通用工具来处理树木。我正在使用 JavaScript,所以我可以强加的东西很少,而且我正在使用我无法更改的现有数据结构。我设法定义了以下内容:
reduceTree :: (T a -> [T a]) -> (b -> T a -> b) -> b -> T a -> b
reduceTree(getChildren, f, accumulator, tree)
(我使用 Haskell 类型签名是因为它们更容易阅读)
这个getChildren 函数是必需的,因为我的树是任意的,我不知道它是如何构造的。
reduceTree 运行良好。但我也想有一个mapTree 函数,最好重用我的reduceTree 函数,但我被卡住了。有什么不对劲,但我不知道是什么。
编辑
我的reduceTree 实现:
export function reduceTree(getChildren, f, accumulator, tree) {
const children = getChildren(tree);
if (!children || children.length === 0) {
return f(accumulator, tree)
} else {
const childrenResult = children.reduce(
(accumulator, subTree) => reduceTree(getChildren, f, accumulator, subTree),
accumulator
);
return f(childrenResult, tree)
}
}
它已经过测试并且可以工作。
(我用来构造/证明上面的javascript的伪Haskell实现:
reduceTree f a (Node val []) = f a val
reduceTree f a (Node val xs) = f (fold (reduceTree f) acc) val
)
【问题讨论】:
-
你知道
mapTree的签名了吗? -
您能否展示一下您对
reduceTree的实现,好吗?我猜它目前不会调用f- 除非你将getChildren更改为getContents :: T a -> (a, [T a])。 -
啊,确实如此 - 但您的
f应该采用a参数,而不是T a。 -
@Bergi 我通过创建
f :: b -> T a -> b来避免处理节点本身的结构。请记住,我实际上使用的是 javascript,所以一切都很松散。 -
@WillNess, @Bergi 我添加了
reduceTree的实现和我的伪代码。请注意,我的“树”只有具有某些值的节点和一个(可能为空的)子级列表。
标签: javascript haskell tree functional-programming fold