лучше использовать HXT и стрелки - PullRequest
3 голосов
/ 04 февраля 2012

Я использовал hxt без проблем, но с самого начала была проблема.Видите, представьте следующий фрагмент кода

liftKeys = atTag "myKeys" >>>
   proc e -> do
      key1 <- getAttrValue "name"   -< e
      key2 <- getAttrValue "chance" -< e
      returnA -< (key1, key2)

Я использовал его так же, как и многие документы для анализа, и перед классической проблемой программирования - отсутствие абстракции.

<zone id= "greenhill">
  <key name="a" chance = "10" />
  <key name="v"  chance = "10"/>
</zone>

У меня есть четыре (и еще больше) файлов для разбора, как в этом примере.У некоторых есть 2 атрибута, у других - 5, у некоторых - 1 и т. Д. Я не могу писать разные версии liftKeys в зависимости от количества атрибутов, которые имеет мой файл.Дело в том, что я действительно не понимаю стрелы или что я делаю. У вас должно быть какое-то сложение или что-то, чтобы написать более простой код.

Знаете ли вы, как лучше использовать это?

1 Ответ

3 голосов
/ 04 февраля 2012

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

arrowList :: Arrow a => [a b c] -> a b [c]
arrowList []         = arr $ const []
arrowList (a:arrows) = proc b -> do
    c  <- a -< b
    cs <- arrowList arrows -< b
    returnA -< (c:cs)

Возможно, что-то подобное уже существует в некоторой библиотеке утилит со стрелками, но я не смог найти ее с помощью быстрого поиска. Здесь, учитывая список стрелок [a b c], мы объединяем их в одну стрелку, сначала вводя b первой стрелке, а затем рекурсивно объединяя остальную часть списка и вводя b этой объединенной стрелке.

Я написал вышеупомянутую функцию, используя обозначение стрелки, чтобы ее было проще объяснить, но вы можете реализовать ее просто так:

arrowList :: Arrow a => [a b c] -> a b [c]
arrowList []         = arr $ const []
arrowList (a:arrows) = a &&& arrowList arrows >>> arr (uncurry (:))

Теперь мы можем реализовать функцию liftKeys следующим образом

liftKeys :: ArrowXml a => [String] -> a XmlTree [String]
liftKeys keys = atTag "myKeys" >>> arrowList (map getAttrValue keys)

И ваш исходный пример выше может быть выражен как liftKeys ["name", "chance"].

...