我一直使用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。问题是我不太了解箭头或我在做什么 必须有一些折叠或其他东西才能编写更简单的代码。
你知道这个更好的用途吗?
如果您有不同数量的属性,那么从属性名称列表构造箭头似乎是最自然的解决方案。然而,要做到这一点,我们需要一个小的辅助函数来将箭头列表转换为生成列表的单个箭头。
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"]
。