Подсчет и фильтрация Стрелка для HXT - PullRequest
6 голосов
/ 03 марта 2011

Я пытаюсь проанализировать XML, но я хочу отфильтровать и извлечь только определенное количество дочерних элементов из данного узла.Например:

<root>
    <node id="a" />
    <node id="b" />
    <node id="c" />
    <node id="d" />
</root>

И тогда, если я выполню стрелку getChildren >>> myFilter 2, я получу обратно только узлы с идентификаторами "a" и "b".

Интуиция дает мнеЯ должен использовать State Arrow, чтобы отслеживать, но я не знаю, как это сделать.

Я пытался сделать это сам, но это не совсем то, что я хочу, выглядит не очень элегантно, и не 'т работа.Я пытаюсь запустить цепочку стрелок с runSLA и целочисленным параметром в качестве начального состояния, а затем определяю:

takeOnly :: IOSLA Int XmlTree XmlTree
takeOnly = changeState (\s b -> s-1)
             >>> accessState (\s b -> if s >= 0 then b else Nothing)

Но, конечно, я не могу вернуть Nothing, мне нужно вернутьXMLTree.Но я вообще не хочу ничего возвращать!

Возможно, есть лучший выход.Вы можете мне помочь?

Спасибо за ваше время и помощь!

1 Ответ

4 голосов
/ 03 марта 2011

Вероятно, было бы более идиоматичным использовать комбинаторы в Control.Arrow.ArrowList для обработки такого рода вещей.

Пакет специально предоставляет (>>.) :: a b c -> ([c] -> [d]) -> a b d, что является "комбинатор для преобразования результата стрелки списка в другой список ".Это позволяет нам использовать функцию take, которая у нас уже есть для списков в этом контексте.

Вот краткая версия того, как вы можете ее использовать:

module Main where

import Text.XML.HXT.Arrow

takeOnly :: (ArrowXml a) => Int -> a XmlTree XmlTree
takeOnly n = getChildren >>. take n 

main = do
  let xml = "<root><node id='a' /><node id='b' />\
                  \<node id='c' /><node id='d' /></root>"

  print =<< runX (readString [] xml >>> getChildren >>> takeOnly 2)

Это, я считаю, делаетпримерно то, что вы ищете:

travis@sidmouth% ./ArrowTake
[NTree (XTag (LP node) [NTree (XAttr (LP id)) [NTree (XText "a") []]]) [],
 NTree (XTag (LP node) [NTree (XAttr (LP id)) [NTree (XText "b") []]]) []]

Нет IOSLA требуется.Обратите внимание, что я также немного изменил тип функции - эта версия мне кажется более приятной, но вы можете легко преобразовать ее в нечто более похожее на тип в вашей версии.

...