 <p>This is one of those cases where type signatures really help. Stare for a second at the type signature: </p> <pre><code>(+=) :: (ArrowXml a) =&gt; a b XmlTree -&gt; a b XmlTree -&gt; a b XmlTree </code></pre> <p>First off, <code>ArrowXml</code> is a subclass of <code>Arrow</code>, which describes some sort of machinery taking some input to some output. You can think of it like a big factory with conveyor belts taking things to different machines, and we're building these factory machines and hence factories with functions. Three of the Arrow combinators, for example, are:</p> <pre><code>(&amp;&amp;&amp;) :: (Arrow a) =&gt; a b c -&gt; a b c' -&gt; a b (c, c') |infixr 3| Fanout: send the input to both argument arrows and combine their output. arr :: (Arrow a) =&gt; (b -&gt; c) -&gt; a b c Lift a function to an arrow. (.) :: (Category cat) =&gt; cat b c -&gt; cat a b -&gt; cat a c morphism composition. </code></pre> <p>Now look at the lowercase letter (type variable) very closely in:</p> <pre><code>(+=) :: (ArrowXml a) =&gt; a b XmlTree -&gt; a b XmlTree -&gt; a b XmlTree </code></pre> <p>Clearly we're taking two machines which turn <code>b</code>s into <code>XmlTree</code>s and "merging them together" into one machine which takes a <code>b</code> in and expels an <code>XmlTree</code>. But importantly, this type signature tells us that more or less the <strong>only</strong> way that this can be implemented is:</p> <pre><code>arr1 += arr2 = arr f . (arr1 &amp;&amp;&amp; arr2) where f :: (XmlTree, XmlTree) -&gt; XmlTree f = _ </code></pre> <p>This is because of "free theorems"; if you don't know the type of a parameter then we can prove that you can't really <em>do</em> much with it. (It can be a little more complicated because the arrow might have structures which aren't totally encapsulated by <code>arr</code>, like internal counters which are summed together with <code>.</code> which are then set to <code>0</code> when using <code>arr</code>. So actually replace <code>arr f</code> with a generic <code>a (XmlTree, XmlTree) XmlTree</code> and you're good to go.)</p> <p>So we must have <strong>parallel execution</strong> of the two arrows here. That's what I'm trying to say. Because the combinator <code>(+=)</code> doesn't know what <code>b</code> is, it has no choice but to blithely feed the <code>b</code> to the arrows in parallel and then try to combine their outputs together. So, <code>deep (hasName "bar")</code> does not look at <code>foo</code>.</p> <p>You can possibly make a mutually recursive solution with <code>deep (hasName "bar") . foo</code> if you really want, but it seems potentially dangerous (i.e. infinite loop), so it may be safer to simply define something like:</p> <pre><code>a ++= b = a += (b . a) </code></pre> <p>where the "current" a is "fed" to b to produce the update. To do this you will have to import <code>.</code> from <code>Control.Category</code> as it is not the same as <code>Prelude..</code> (which does function composition only). This looks like:</p> <pre><code>import Prelude hiding ((.)) import Control.Category ((.)) </code></pre>