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