2012-04-21 74 views
2

我试图使用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,但我一直无法将所有的东西放在一起。起初听起来很有希望,但是该函数仅仅停止了特定子树的处理,所以它仍然会转换除嵌套元素之外的所有元素。

回答

1

我不知道我完全了解这个问题,但我会尽力回答:)

让我们尝试下:

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)并纯粹处理它们。

所以,解决方案并不理想,但我希望它能帮助你作为一个起点。