我试图了解如何使用 Traversable 迭代我的树数据结构。我有一棵看起来像这样的丑树(实际上是森林):
data ParseTree a = Leaf a | Node a (ParseTree a) (ParseTree a) | MultiNode a [ParseTree a]
deriving (Show, Functor, F.Foldable, T.Traversable)
t = Node S
(Node NP (Leaf DP) (Leaf NP))
(MultiNode VP
[Node VP (Node VP (Leaf VP) (Leaf PP)) (Node NP (Leaf DP) (Leaf NP)),
Node VP (Leaf VP) (Node PP (Leaf PP) (Node NP (Leaf DP) (Leaf NP)))]
)
我想找到多节点,这样我就可以替换构建新树,多节点中的每个项目一个。
对我来说编写这样的函数很容易
findmulti :: ParseTree a -> [ParseTree a]
findmulti (Leaf a) = []
findmulti (Node a left right) = findmulti left ++ findmulti right
findmulti (MultiNode a lst) = [ (MultiNode a lst) ]
但我认为我应该能够使用 traverse 来查看列表并为我找到项目。如果我做
traverse print t
我只得到最后的值:
S NP DP NP VP VP VP VP PP...
但我实际上希望遍历在多节点处停止。如何控制遍历的深度?或者这是不可能的,因为 Traversable 和朋友对容器是不可知的?
最终我想获得允许我替换多节点的镜头,但现在我只是想了解可遍历的工作原理。我是否使用了正确的工具来完成这项工作?