HXT: left factoring non-deterministic arrows?

I am trying to come to terms with the Haskell XML Toolbox ( HXT ) and I am somewhere on the wall because I do not seem to fully capture the arrows as a computing tool.

Here is my problem, which I was hoping to illustrate a bit with a GHCi session:

> let parse p = runLA (xread >>> p) "<root><a>foo</a><b>bar</b><c>baz</c></root>" > :t parse parse :: LA XmlTree b -> [b] 

So, Parse is a small helper function that applies any arrow that I pass into a trivial XML document

 <root> <a>foo</a> <b>bar</b> <c>baz</c> </root> 

I define another helper function, this time extracting text under a node with the given name:

 > let extract s = getChildren >>> isElem >>> hasName s >>> getChildren >>> getText > :t extract extract :: (ArrowXml cat) => String -> cat (Data.Tree.NTree.TypeDefs.NTree XNode) String > parse (extract "a" &&& extract "b") -- extract two nodes' content. [("foo","bar")] 

Using this function, it is easy to use the &&& combinator to combine the text of two different nodes, and then, say, pass it to the constructor, for example:

 > parse (extract "a" &&& extract "b" >>^ arr (\(a,b) -> (b,a))) [("bar","foo")] 

Now comes the part that I don’t understand: I want the left factor! extract twice calls getChildren on the root node. Instead, I would only like to call him once! So I first get the child root of node

 > let extract' s = hasName s >>> getChildren >>> getText > :t extract' extract' :: (ArrowXml cat) => String -> cat XmlTree String > parse (getChildren >>> isElem >>> (extract' "a" &&& extract' "b")) [] 

Note that I tried to reorder calls, say, isElem, etc. to find out if this is a problem. But, since this is so, I just do not know why this does not work. There is a “tutorial” arrow on the Haskell wiki, and as I understand it, it should be possible to do what I want to do this way - namely, use &&& to compare the results of the two calculations.

This also works, but only at the beginning of the chain of arrows, and not in the middle of the aisle, when I have some results, I want to keep the "general". I have a feeling that I just can’t wrap my head in the difference in ideas between a normal functional composition and the designation of an arrow. I would really appreciate any pointers! (Even if it's just some kind of general arrow tutorial that goes a little deeper than the Haskell-wiki.)

Thanks!

+7
haskell arrows hxt
source share
1 answer

If you convert the arrow to (and then from) a deterministic version, this works as expected:

 > let extract' s = unlistA >>> hasName s >>> getChildren >>> getText > parse (listA (getChildren >>> isElem) >>> (extract' "a" &&& extract' "b")) [("foo","bar")] 
However, this is not very satisfactory, and I can’t remember what (&&&) does in this way with a non-deterministic arrow (I personally used proc/do notation for something much more complicated than that).

UPDATE: Here, something strange seems to be happening with runLA and xread . If you use runX and readString , everything works as expected:

 > let xml = "<root><a>foo</a><b>bar</b><c>baz</c></root>" > let parse p = runX (readString [] xml >>> p) > let extract' s = getChildren >>> hasName s >>> getChildren >>> getText > parse (getChildren >>> isElem >>> (extract' "a" &&& extract' "b")) [("foo","bar")] 

This means that you must run the parser in the IO monad, but in any case there are advantages when using runX (better error messages, etc.).

+2
source share

All Articles