2012-04-21 4 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, но мне не удалось собрать все части вместе. processTopDownUntil сначала казался перспективным, но эта функция только останавливает обработку для определенного поддерева, поэтому она все равно преобразует все элементы, исключая вложенные.

ответ

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), и обработать их чисто.

Итак, решение не является идеальным, но я надеюсь, что это поможет вам в качестве отправной точки.

Смежные вопросы