I ve been using hxt with no problem, but there was a problem since the beginning. See, imagine the following piece of code
liftKeys = atTag "myKeys" >>>
proc e -> do
key1 <- getAttrValue "name" -< e
key2 <- getAttrValue "chance" -< e
returnA -< (key1, key2)
I have used it like that trough many documents to parse, and im before the classic programmig problem, lack of abstraction.
<zone id= "greenhill">
<key name="a" chance = "10" />
<key name="v" chance = "10"/>
</zone>
I have four (and more coming) files to parse like this example. Some have 2 attributes, others have 5 , someothers 1 etc I cant be writing different versions of liftKeys according the amount of attributes my file has. The thing is i dont really understand arrows or what im doing u.u There has to be some fold or something to write more simple code.
Do you know a better use of this?
If you have a differing number of attributes, then it seems like the most natural solution to construct an arrow from a list of attribute names. However, to do that, we are going to need a small helper function to turn a list of arrows into a single arrow that produces a list.
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)
Probably something like this already exists in some arrow utility library, but I wasn't able to find one with a quick search. Here, given a list of arrows [a b c]
, we merge them into a single arrow by first feeding b
to the first arrow and then recursively merging the rest of the list and feeding b
to that merged arrow.
I wrote the above function using the arrow notation to make it easier to explain, but you could implement it simply like this:
arrowList :: Arrow a => [a b c] -> a b [c]
arrowList [] = arr $ const []
arrowList (a:arrows) = a &&& arrowList arrows >>> arr (uncurry (:))
Now we can implement the liftKeys
function like this
liftKeys :: ArrowXml a => [String] -> a XmlTree [String]
liftKeys keys = atTag "myKeys" >>> arrowList (map getAttrValue keys)
And your original example above could be expressed as liftKeys ["name", "chance"]
.