Andrey Chudnov achudnov at gmail.com
Thu Sep 3 04:06:04 UTC 2015

```I thought I'd add an example of what I'm trying to do and what I think
transformMOnOff might be very helpful with... that is, if I only knew
how to use it. So suppose I have two mutrec data types,

> data A = A [A] | B B | I Int
> data B = B [A]

Suppose I want to write a function

> incrementByNestingDepth :: A -> A

that would traverse the tree and increment all the I's by their nesting
depth in B, e.g.

> incrementByNestingDepth (A [I 1, I 3, B [ A [I 2], B [I 1]]]) = A [I
1, I 3, B [A [I 3], B [I 3]]]

I could write that with just recursion on A and B, which could get
tedious if I had several datatypes with 20 constructors each. Or I could
use uniplate. But that's still quite tedious:

> incrementByNestingDepth a = runState (incrementM a) 0
> incrementM :: A -> State Int A
> incrementM a = case a of
>      I i -> liftM (A . (i +)) get
>      B b->liftM B \$ descendBiM incrementM b
>      _  -> descendM incrementM a

The code isn't much smaller than for a handwritten traversal and you
could imagine (or take my word for it) that one still doesn't see a lot
of saved space using uniplate with more elaborate examples.

Now, don't get me wrong: I'm not saying uniplate is useless. In fact,
it's one of the most useful libraries I've ever used. It's simple and
does sheer magic more often than not.

However, for the sake of compositionality what (I think) one would like
to do in this case is have two traversals: the outer which says "for
every B, transform its A-children recursively like this" and the inner
says "for every A, transform all of its children recursively, but until
you see a B". You can't really do that with transform/rewrite in
uniplate, so one has to fall back to descend which requires you to set

The documentation in Control.Lens.Plated alludes that the traversal
above might just be possible using transformOnOff, but, unfortunately,
it does not go into any detail how exactly could one achieve that.

/Andrey

On 09/02/2015 09:31 PM, mantkiew at gsd.uwaterloo.ca wrote:
> +1 I've been missing such examples for a long time too.
>
> Michał
>
>    Original Message
> From: Andrey Chudnov
> Sent: Wednesday, September 2, 2015 7:44 PM
> Subject: [Haskell-cafe] Examples for Control.Lens.Plated?
>
> Hello Cafe,
> I'm considering porting some of my code that uses uniplate to lens. But
> Control.Lens.Plated is giving me headaches. So I'm looking for remedy.
>
> Has anyone used it and willing to share examples? I hope that seeing
> some of the combinators in action would help me understand the type
> signatures and documentation. What I'm particularly interested in is the
> following:
> 1) implementation of something like transformBi and rewriteBi using lens
> 2) usage of *On, *Off and *OnOff combinators (e.g., transformMOn,
> transformMOff, transformMOnOff). What I want to understand is the
> difference between the 3 variants. Also, what does it mean to "Transform
> every element in the tree in a region indicated by a supplied Traversal"
> and how exactly does the traversal define the region.
> 3) any recursive tree traversals/transformations using Plated that stop
> the recursion at a certain point (e.g., upon seeing a certain constructor)
>
> I hope this isn't too vague, but, please, let me know if it is.
>
> /Andrey
> _______________________________________________