2012-04-21 57 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)並純粹處理它們。

所以,解決方案並不理想,但我希望它能幫助你作爲一個起點。

相關問題