【发布时间】:2021-12-22 13:49:34
【问题描述】:
我编写了一个函数,它使用任何类型的遍历将二叉树收集到属于Monoid 类型类的任何类型。
树的类型定义如下:
data BinTree a = EmptyBT |
NodeBT a (BinTree a) (BinTree a)
deriving (Eq, Ord, Show)
不同类型遍历的枚举类型:
data TravOrder = Inorder | Preorder | Postorder
我第一次尝试编写函数:
collectBT :: Monoid m => TravOrder -> (a -> m) -> BinTree a -> m
collectBT Inorder = \f tree ->
case tree of
EmptyBT -> mempty
NodeBT val lt rt -> recursion lt <> f val <> recursion rt
where recursion = collectBT Inorder f
collectBT Preorder = \f tree ->
case tree of
EmptyBT -> mempty
NodeBT val lt rt -> f val <> recursion lt <> recursion rt
where recursion = collectBT Preorder f
collectBT Postorder = \f tree ->
case tree of
EmptyBT -> mempty
NodeBT val lt rt -> recursion lt <> recursion rt <> f val
where recursion = collectBT Postorder f
此版本运行正常。然后我删除了重复的代码:
combineInOrder :: Monoid m => TravOrder -> m -> m -> m -> m
combineInOrder Inorder = \val lt rt -> lt <> val <> rt
combineInOrder Preorder = \val lt rt -> val <> lt <> rt
combineInOrder Postorder = \val lt rt -> lt <> rt <> val
collectBT' :: Monoid m => TravOrder -> (a -> m) -> BinTree a -> m
collectBT' ord f EmptyBT = mempty
collectBT' ord f (NodeBT val rt lt) =
let recursion = collectBT ord f
in combineInOrder ord (f val) (recursion lt) (recursion rt)
现在函数返回不正确的结果。我认为它的行为方式应该相同,因为 monoids 以相同的顺序组合。我错过了什么?
表达式生成简单树以防有人想运行它:
(NodeBT 1 (NodeBT 2 EmptyBT EmptyBT) (NodeBT 3 EmptyBT EmptyBT))
1
/ \
2 3
【问题讨论】:
-
你在
recursion中调用collectBT(不是collectBT')? -
你写
NodeBT val rt lt作为你的模式。你的意思可能是NodeBT val lt rt。 -
@DanielWagner 就是这样。谢谢!我在这上面浪费了太多时间。
-
“不正确的结果”。 -- 布尔失明再次来袭!