Подсчет и фильтрация Arrow для HXT

Я пытаюсь проанализировать 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. Но я вообще ничего не хочу возвращать!

Там, вероятно, лучший выход. Можешь мне помочь?

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


person Jorge Diz    schedule 03.03.2011    source источник


Ответы (1)


Вероятно, было бы более идиоматично использовать комбинаторы в 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 не требуется. Обратите внимание, что я также немного изменил тип функции — эта версия кажется мне более приятной, но вы можете легко преобразовать ее во что-то более похожее на тип в вашей версии.

person Travis Brown    schedule 03.03.2011
comment
Вау! Это именно то, что я искал, спасибо! Как видно, я новичок в стрелах... но я люблю их, теперь даже больше ^^ - person Jorge Diz; 04.03.2011