HXT 的计数和过滤箭头

问题描述 投票:0回答:1

我正在尝试解析 XML,但我想从给定节点中过滤并仅提取确定数量的子节点。例如:

<root>
    <node id="a" />
    <node id="b" />
    <node id="c" />
    <node id="d" />
</root>

然后,如果我执行箭头

getChildren >>> myFilter 2
,我将只返回 id 为“a”和“b”的节点。

直觉告诉我应该使用状态箭头来跟踪,但我不知道该怎么做。

我尝试自己做,但这并不完全是我想要的,看起来不太优雅,而且不起作用。我尝试使用

runSLA
和整数参数作为初始状态运行我的箭头链,然后定义:

takeOnly :: IOSLA Int XmlTree XmlTree
takeOnly = changeState (\s b -> s-1)
             >>> accessState (\s b -> if s >= 0 then b else Nothing)

但是我当然不能返回

Nothing
,我需要返回一个XmlTree。但我根本不想退货!

可能有更好的出路。你能帮我吗?

感谢您的时间和帮助!

haskell state hxt arrow-abstraction
1个回答
4
投票

使用 Control.Arrow.ArrowList 中的组合器来处理这种事情可能会更惯用。

该包特别提供了

(>>.) :: a b c -> ([c] -> [d]) -> a b d
,它是一个“将列表箭头的结果转换为另一个列表的组合器”。这允许我们在这种情况下使用我们已经拥有的用于列表的
take
函数。

以下是如何使用它的快速版本:

module Main where

import Text.XML.HXT.Arrow

takeOnly :: (ArrowXml a) => Int -> a XmlTree XmlTree
takeOnly n = getChildren >>. take n 

main = do
  let xml = "<root><node id='a' /><node id='b' />\
                  \<node id='c' /><node id='d' /></root>"

  print =<< runX (readString [] xml >>> getChildren >>> takeOnly 2)

我相信这大约符合您的要求:

travis@sidmouth% ./ArrowTake
[NTree (XTag (LP node) [NTree (XAttr (LP id)) [NTree (XText "a") []]]) [],
 NTree (XTag (LP node) [NTree (XAttr (LP id)) [NTree (XText "b") []]]) []]

无需

IOSLA
。请注意,我还稍微更改了函数类型 - 这个版本对我来说似乎更好,但您可以轻松地将其转换为更像您版本中的类型。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.