This is the closest I've got using the wander function:
_relatives :: Traversal' Node Node
_relatives = wander tra
where
tra1 :: forall f. Applicative f => (Node -> f Node) -> Node → f Node
tra1 = traverseOf _children
tra2 :: forall f. Applicative f => (Node -> f Node) -> Node → f Node
tra2 = traverseOf _siblings
tra :: forall f. Applicative f => (Node -> f Node) -> Node → f Node
tra g w = lift2 combine fw' fw''
where
fw' = tra1 g w
fw'' = tra2 g w
combine (Node w') (Node w'') = Node (w' { siblings = w''.siblings })
If only I could get rid of this last line...
combine (Node w') (Node w'') = Node (w' { siblings = w''.siblings })
Ideally, my tra would be like so (chaining result of tra1 into tra2):
tra :: forall f. Monad f => (Node -> f Node) -> Node -> f Node
tra g w = tra2 g =<< tra1 g w
But I can't do that, because wander asks for Applicative constraint and not a Monad. And I can't chain the results of Applicative.
I can also do this generically if my Node implements Semigroup:
tra :: forall f. Applicative f => (Node -> f Node) -> Node -> f Node
tra g w = lift2 append fw' fw''
where
fw' = tra1 g w
fw'' = tra2 g w
But I don't have Semigroup for my real use-case...
Is there really no generic way to combine two traversals?
I really hope someone can come up with better approach. If not, I'll mark this answer as accepted after a while.
EDIT:
Turns out I'm not the only one wishing to do that, and apparently it's impossible due to the "sequencing" nature of such transformation - it requires a Monad while we only have an Applicative https://github.com/ekmett/lens/issues/109
Going to accept this answer since there is probably no better answer than "there is no answer".
node # _relatives .~ anotherNodedo? Does it set children? Or siblings? Or both? - Fyodor Soikin.~is aset, right? So itsset _relatives anotherNode node. Well, I think it must set both to satisfy the lens laws. I'm not sure though. - MnZrK