Haskell - 如何基于二叉树的文件夹创建 mapTree 函数?

标签 haskell tree binary fold map-function

这是“Haskell Programming from first principles”第 11 章代数数据类型中的一道题:

data BinaryTree a =
  Leaf
  | Node (BinaryTree a) a (BinaryTree a)
  deriving (Eq, Ord, Show)

我们实际上并没有将一个值插入到现有的树中;每次我们想向数据结构中插入一个值时,我们都会构建一棵全新的树:

insert' :: Ord a => a -> BinaryTree a -> BinaryTree a
insert' b Leaf = Node Leaf b Leaf
insert' b (Node left a right)
  | b == a = Node left a right
  | b < a = Node (insert' b left) a right
  | b > a = Node left a (insert' b right)

这是二叉树数据结构的映射函数:

mapTree :: (a -> b) -> BinaryTree a -> BinaryTree b
mapTree _ Leaf = Leaf
mapTree f (Node left a right) = 
  Node (mapTree f left) (f a) (mapTree f right)

为二叉树写入文件夹

根据我们提供的 BinaryTree 的定义,为二叉树编写一个变形。

-- any traversal order is fine
foldTree :: (a -> b -> b) 
  -> b 
  -> BinaryTree a 
  -> b

上面的类型是对那些在应用折叠功能之前不将树转换为列表的人的提示。

为二叉树重写映射

使用您刚刚编写的 foldTree,使用 foldTree 重写 mapTree。 没有 Ord 约束是有意的,您不需要使用插入功能。

mapTree' :: (a -> b)
  -> BinaryTree a
  -> BinaryTree b
mapTree' f bt =
  foldTree undefined undefined undefined

在以下方面的大量帮助下,我设法得到了适用于第一个有关 foldr 的问题的答案: https://github.com/johnchandlerburnham/hpfp/blob/master/11/BinaryTree.hs

我的回答:

foldTree f b Leaf = b
foldTree f b (Node left a right) 
  = (foldTree f tempb left) where
    tempb = (f a) tempright
    tempright = foldTree f b right

但是,对于第二个关于为二叉树编写新的 mapTree 的问题,我找不到答案。上面提供了原始的 mapTree。即使是 johnchandlerburnham link 处的答案使用不同的折叠树。

有人可以根据我对第一个问题的回答,帮助获得第二个问题的可行答案吗?或者是否需要第一个问题的另一个答案?

用于测试的树可以是:

testTree :: BinaryTree Integer
testTree =
  Node (Node Leaf 3 Leaf) 1 (Node Leaf 4 Leaf)

最佳答案

您不能使用具有该签名的 foldTree 编写 mapTree。 (正如@chi 指出的那样,技术问题是 foldTree 的签名错误,无法成为 BinaryTree 的真正变形。)事实上,如果您加载链接的 Haskell 文件BinaryTree.hs ,您会看到那里的 mapTree' 无法正常工作:

λ> :l BinaryTree
λ> mapTree (+1) testTree
Node (Node Leaf 2 Leaf) 3 (Node Leaf 4 Leaf)
λ> mapTree' (+1) testTree
Node (Node (Node Leaf 3 Leaf) 2 Leaf) 4 Leaf

它给出了正确的节点值,但是树的结构是错误的。

我没有那本书的副本,所以我无法确切地看到你所看到的,但也许 these notes会有帮助。在 11.15 节的最后,作者谈到了 foldTree 的 2 参数和 3 参数版本,并表明只有 mapTree' 编写为使用 3 参数版本将正常工作。

关于Haskell - 如何基于二叉树的文件夹创建 mapTree 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63547939/

相关文章:

haskell - Control.Monad.State API 最近是否发生了变化?

algorithm - 存储有关在 d 天访问过 w 网页的 u 客户数据的好方法

C: 抑制来自二进制的系统调用

php - PHP如何获取二进制的post数据

java - 这个Java算法如何更快

validation - Haskell:检查字符串是否为有效数字

Haskell,终端调用优化和懒惰求值

haskell - 为什么 Haskell 无法解析 "overloaded"运算符?

javascript - 如果选择了所有子节点,如何将父树节点标记为已选择

algorithm - 树遍历以层次优先顺序和深度优先顺序递归