HXT:如何在第一次成功转换后停止处理?
问题描述:
我试图使用Control.Arrow.ArrowTree构建一个HTML处理箭头,该箭头在给定树中第一次成功转换(深度优先)后停止。即同类型HXT:如何在第一次成功转换后停止处理?
processFirst :: (ArrowTree a, Tree t) => a (t b) (t b) -> a (t b) (t b)
例如,要添加的类别“第一次”的第一个列表项的HTML文档中的一个功能,一个可以建立箭头
processFirst (hasName "li" `guards` addAttr "class" "first")
我是相当新到HXT,我一直在阅读API文档几个小时,并试图找出如何实现processFirst
,但我一直无法将所有的东西放在一起。起初听起来很有希望,但是该函数仅仅停止了特定子树的处理,所以它仍然会转换除嵌套元素之外的所有元素。
答
我不知道我完全了解这个问题,但我会尽力回答:)
让我们尝试下:
test = flip runLA undefined $ xshow $
constA "<xml><x>X1</x><x>X2</x></xml>" >>> xread
>>> processFirst (hasName "x" `guards` addAttr "class" "first")
processFirst f = f `orElse` processChildren (processFirst f)
的processFirst
的定义是一样的定义processTopDownUntil
。此功能将输出类似:
["<xml><x class=\"first\">X1</x><x class=\"first\">X2</x></xml>"]
的问题应该是明确的 - 如果f
失败为*节点,然后processFirst
将要求每一个孩子。如果f
对某个孩子成功,我们需要一种方式来中止其他孩子的处理。
可能的解决办法是使用状态箭头:
processFirst f = fromSLA False process
where
process = (getState >>> isA not)
`guards`
(f >>> changeState (const $ const True))
`orElse`
processChildren process
的想法是设置状态时f
成功并在处理前检查。
注意:现在f
应该是SLA
箭头。如果不是你想要的,你可以尝试收集所有的孩子(例如使用listA
)并纯粹处理它们。
所以,解决方案并不理想,但我希望它能帮助你作为一个起点。