[Haskell-cafe] Examples for Control.Lens.Plated?

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 
up your recursion yourself.

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.


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
> To: haskell-cafe
> 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
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

More information about the Haskell-Cafe mailing list