3

我一直在使用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。问题是我真的不明白箭头或我在做什么 uu 必须有一些折叠或一些东西来编写更简单的代码。

你知道这个更好的用途吗?

4

1 回答 1

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

于 2012-02-04T11:51:25.130 回答