更好地使用HXT和箭头

时间:2012-02-04 01:30:05

标签: haskell arrows hxt

我一直在使用hxt没有问题,但从一开始就出现了问题。 看,想象下面的一段代码

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

我使用它就像通过许多文档来解析,并且在经典的programmig问题之前,我缺乏抽象。

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

我有四个(以及更多即将发布的)文件要解析,就像这个例子一样。有些有2个属性,有些有5个,有些有1个等等 我根据文件的属性数量不能编写不同版本的liftKeys。事情是我真的不明白箭头或我正在做什么u.u 必须有一些折叠或其他东西来编写更简单的代码。

你知道更好地利用这个吗?

1 个答案:

答案 0 :(得分:3)

如果您拥有不同数量的属性,那么从属性名称列表构建箭头似乎是最自然的解决方案。但是,要做到这一点,我们需要一个小帮助函数将箭头列表转换为生成列表的单箭头。

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"]