6

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 を返す必要があります。しかし、私は何も返したくありません!

そこにはおそらくもっと良い方法があります。手伝って頂けますか?

お時間をいただきありがとうございます。

4

1 に答える 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。関数の型も少し変更したことに注意してください。このバージョンの方が見栄えが良いように思えますが、自分のバージョンに近い型に簡単に変換できます。

于 2011-03-03T10:16:36.437 に答える