Question

I'm trying to use Control.Arrow.ArrowTree to build a HTML processing arrow that stops after the first successful transformation (depth-first) in the given tree. I.e. a function with the type

processFirst :: (ArrowTree a, Tree t) => a (t b) (t b) -> a (t b) (t b)

For example, to add the class "first" to the very first list item in a HTML document, one could build the arrow

processFirst (hasName "li" `guards` addAttr "class" "first")

I'm rather new to HXT and I've been reading the API docs for a couple of hours now and trying to figure out how to implement processFirst, but I haven't been able to fit all the pieces together. processTopDownUntil sounded promising at first, but that function only stops the processing for a particular sub-tree, so it will still transform all elements excluding nested ones.

Was it helpful?

Solution

I'm not sure I completely understood the question, but I'll try to answer :)

Lets try the next:

test = flip runLA undefined $ xshow $
  constA "<xml><x>X1</x><x>X2</x></xml>" >>> xread
  >>> processFirst (hasName "x" `guards` addAttr "class" "first")

processFirst f = f `orElse` processChildren (processFirst f)

The definition of processFirst is the same as definition of processTopDownUntil. This function will output something like:

["<xml><x class=\"first\">X1</x><x class=\"first\">X2</x></xml>"]

The problem should be clear -- if f fails for the top node, then processFirst will be called for every child. We need a way to abort processing of the other children if f succeeded on some child.

Possible solution could be to use state arrow:

processFirst f = fromSLA False process
  where
  process = (getState >>> isA not)
            `guards`
            (f >>> changeState (const $ const True))
            `orElse`
            processChildren process

The idea is to set state when f succeeded and check it before processing.

Note: now f should be SLA arrow. If it is not what you want, the you can try to collect all children (using e.g. listA) and process them purely.

So, the solution is not ideal, but I hope it will help you as a starting point.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top