Question about zippers on trees

Hello Cafe! I am trying to modify a large 'Data.Tree.Tree'. I managed to modify node labels with specific indices in the form of @[Int]@ as they are defined in, for example, 'Control.Lens.At.Ixed' or 'Lens.Micro.GHC'. However, I also need to 1. modify the node label using information from nearby nodes (e.g., the children); 2. modify the tree structure itself; for example, I may want to change the sub-forest. Basically, I need a lens that focuses not on the node label, but on the node itself. I perceived that this is more difficult. I tried to use 'Control.Zipper'. I can use zippers to achieve point 1, albeit in a complicated way: (1) I need to go downwards to focus the specific node; (2) I need to traverse the children to collect data and save the data somewhere (how? in let bindings?); (3) I then go back upwards and change the node label using the collected data. Even so, I do not really manage to change the actual structure of the tree. I also briefly had a look at plates, but do not manage to use them in a proper way, maybe because the depth of my structures may be several hundred levels. Did you encounter similar problems in the past or could you point me to resources discussing these issues? Thank you! Dominik

From containers, Tree is defined as:
data Tree a = Node
{ label :: a
, children :: [Tree a]
}
(I've renamed the record labels.) What is a zipper into such a tree? I think
that the [rosezipper](
https://hackage.haskell.org/package/rosezipper-0.2/docs/Data-Tree-Zipper.htm...
)
library gives a good definition. I'll specialized it to rose trees:
data TreePos a = Loc
{ _content :: Tree a -- ^ The currently selected tree.
, _before :: [Tree a] -- ^ Forest to the left
, _after :: [Tree a] -- ^ Forest to the right
, _parents :: [([Tree a], a, [Tree a])] -- ^ Finger to the selected
tree
}
I think that does it. I wouldn't recommend using a library for this kind
though. Just define `TreePos` in your code and then write the functions
that you happen to need.
On Wed, Jul 22, 2020 at 7:41 AM Dominik Schrempf
Hello Cafe!
I am trying to modify a large 'Data.Tree.Tree'. I managed to modify node labels with specific indices in the form of @[Int]@ as they are defined in, for example, 'Control.Lens.At.Ixed' or 'Lens.Micro.GHC'.
However, I also need to 1. modify the node label using information from nearby nodes (e.g., the children); 2. modify the tree structure itself; for example, I may want to change the sub-forest.
Basically, I need a lens that focuses not on the node label, but on the node itself. I perceived that this is more difficult.
I tried to use 'Control.Zipper'. I can use zippers to achieve point 1, albeit in a complicated way: (1) I need to go downwards to focus the specific node; (2) I need to traverse the children to collect data and save the data somewhere (how? in let bindings?); (3) I then go back upwards and change the node label using the collected data. Even so, I do not really manage to change the actual structure of the tree. I also briefly had a look at plates, but do not manage to use them in a proper way, maybe because the depth of my structures may be several hundred levels.
Did you encounter similar problems in the past or could you point me to resources discussing these issues?
Thank you! Dominik
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- -Andrew Thaddeus Martin

Thank you for your fast answer.
A direct implementation without using a library is interesting, thank you. I
refrained from doing that, because I thought that Control.Zipper would actually
do this for me. Actually, I was pretty successful with using Control.Zipper to
change node labels, but failed doing more complicated stuff.
Andrew Martin
From containers, Tree is defined as:
data Tree a = Node { label :: a , children :: [Tree a] }
(I've renamed the record labels.) What is a zipper into such a tree? I think that the [rosezipper]( https://hackage.haskell.org/package/rosezipper-0.2/docs/Data-Tree-Zipper.htm... ) library gives a good definition. I'll specialized it to rose trees:
data TreePos a = Loc { _content :: Tree a -- ^ The currently selected tree. , _before :: [Tree a] -- ^ Forest to the left , _after :: [Tree a] -- ^ Forest to the right , _parents :: [([Tree a], a, [Tree a])] -- ^ Finger to the selected tree }
I think that does it. I wouldn't recommend using a library for this kind though. Just define `TreePos` in your code and then write the functions that you happen to need.
On Wed, Jul 22, 2020 at 7:41 AM Dominik Schrempf
wrote: Hello Cafe!
I am trying to modify a large 'Data.Tree.Tree'. I managed to modify node labels with specific indices in the form of @[Int]@ as they are defined in, for example, 'Control.Lens.At.Ixed' or 'Lens.Micro.GHC'.
However, I also need to 1. modify the node label using information from nearby nodes (e.g., the children); 2. modify the tree structure itself; for example, I may want to change the sub-forest.
Basically, I need a lens that focuses not on the node label, but on the node itself. I perceived that this is more difficult.
I tried to use 'Control.Zipper'. I can use zippers to achieve point 1, albeit in a complicated way: (1) I need to go downwards to focus the specific node; (2) I need to traverse the children to collect data and save the data somewhere (how? in let bindings?); (3) I then go back upwards and change the node label using the collected data. Even so, I do not really manage to change the actual structure of the tree. I also briefly had a look at plates, but do not manage to use them in a proper way, maybe because the depth of my structures may be several hundred levels.
Did you encounter similar problems in the past or could you point me to resources discussing these issues?
Thank you! Dominik
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

It appears that you've already discovered this, but my experience with
zippers has been that abstractions that generalize them are cumbersome,
make type signatures more confusing, and don't really do that much work for
me. Maybe there are other users that don't have this experience, but I
prefer a more direct route with less generalization when I'm working with
zippers.
On Wed, Jul 22, 2020 at 8:02 AM Dominik Schrempf
Thank you for your fast answer.
A direct implementation without using a library is interesting, thank you. I refrained from doing that, because I thought that Control.Zipper would actually do this for me. Actually, I was pretty successful with using Control.Zipper to change node labels, but failed doing more complicated stuff.
Andrew Martin
writes: From containers, Tree is defined as:
data Tree a = Node { label :: a , children :: [Tree a] }
(I've renamed the record labels.) What is a zipper into such a tree? I think that the [rosezipper](
) library gives a good definition. I'll specialized it to rose trees:
data TreePos a = Loc { _content :: Tree a -- ^ The currently selected tree. , _before :: [Tree a] -- ^ Forest to the left , _after :: [Tree a] -- ^ Forest to the right , _parents :: [([Tree a], a, [Tree a])] -- ^ Finger to the selected tree }
I think that does it. I wouldn't recommend using a library for this kind though. Just define `TreePos` in your code and then write the functions that you happen to need.
On Wed, Jul 22, 2020 at 7:41 AM Dominik Schrempf < dominik.schrempf@gmail.com> wrote:
Hello Cafe!
I am trying to modify a large 'Data.Tree.Tree'. I managed to modify node labels with specific indices in the form of @[Int]@ as they are defined in, for example, 'Control.Lens.At.Ixed' or 'Lens.Micro.GHC'.
However, I also need to 1. modify the node label using information from nearby nodes (e.g., the children); 2. modify the tree structure itself; for example, I may want to change
https://hackage.haskell.org/package/rosezipper-0.2/docs/Data-Tree-Zipper.htm... the
sub-forest.
Basically, I need a lens that focuses not on the node label, but on the node itself. I perceived that this is more difficult.
I tried to use 'Control.Zipper'. I can use zippers to achieve point 1, albeit in a complicated way: (1) I need to go downwards to focus the specific node; (2) I need to traverse the children to collect data and save the data somewhere (how? in let bindings?); (3) I then go back upwards and change the node label using the collected data. Even so, I do not really manage to change the actual structure of the tree. I also briefly had a look at plates, but do not manage to use them in a proper way, maybe because the depth of my structures may be several hundred levels.
Did you encounter similar problems in the past or could you point me to resources discussing these issues?
Thank you! Dominik
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- -Andrew Thaddeus Martin

Shouldn’t that be: _before :: [TreePos a] etc.? Jeff
On Jul 22, 2020, at 4:54 AM, Andrew Martin
wrote: From containers, Tree is defined as:
data Tree a = Node { label :: a , children :: [Tree a] }
(I've renamed the record labels.) What is a zipper into such a tree? I think that the [rosezipper](https://hackage.haskell.org/package/rosezipper-0.2/docs/Data-Tree-Zipper.htm...) library gives a good definition. I'll specialized it to rose trees:
data TreePos a = Loc { _content :: Tree a -- ^ The currently selected tree. , _before :: [Tree a] -- ^ Forest to the left , _after :: [Tree a] -- ^ Forest to the right , _parents :: [([Tree a], a, [Tree a])] -- ^ Finger to the selected tree }
I think that does it. I wouldn't recommend using a library for this kind though. Just define `TreePos` in your code and then write the functions that you happen to need.
On Wed, Jul 22, 2020 at 7:41 AM Dominik Schrempf
wrote: Hello Cafe! I am trying to modify a large 'Data.Tree.Tree'. I managed to modify node labels with specific indices in the form of @[Int]@ as they are defined in, for example, 'Control.Lens.At.Ixed' or 'Lens.Micro.GHC'.
However, I also need to 1. modify the node label using information from nearby nodes (e.g., the children); 2. modify the tree structure itself; for example, I may want to change the sub-forest.
Basically, I need a lens that focuses not on the node label, but on the node itself. I perceived that this is more difficult.
I tried to use 'Control.Zipper'. I can use zippers to achieve point 1, albeit in a complicated way: (1) I need to go downwards to focus the specific node; (2) I need to traverse the children to collect data and save the data somewhere (how? in let bindings?); (3) I then go back upwards and change the node label using the collected data. Even so, I do not really manage to change the actual structure of the tree. I also briefly had a look at plates, but do not manage to use them in a proper way, maybe because the depth of my structures may be several hundred levels.
Did you encounter similar problems in the past or could you point me to resources discussing these issues?
Thank you! Dominik
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- -Andrew Thaddeus Martin _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

If you want an abstract solution, there's https://hackage.haskell.org/package/lens-3.2/docs/Control-Lens-Zipper.html. On Wed, Jul 22, 2020 at 9:20 AM Jeff Clites via Haskell-Cafe < haskell-cafe@haskell.org> wrote:
Shouldn’t that be:
_before :: [TreePos a]
etc.?
Jeff
On Jul 22, 2020, at 4:54 AM, Andrew Martin
wrote: From containers, Tree is defined as:
data Tree a = Node { label :: a , children :: [Tree a] }
(I've renamed the record labels.) What is a zipper into such a tree? I think that the [rosezipper]( https://hackage.haskell.org/package/rosezipper-0.2/docs/Data-Tree-Zipper.htm... ) library gives a good definition. I'll specialized it to rose trees:
data TreePos a = Loc { _content :: Tree a -- ^ The currently selected tree. , _before :: [Tree a] -- ^ Forest to the left , _after :: [Tree a] -- ^ Forest to the right , _parents :: [([Tree a], a, [Tree a])] -- ^ Finger to the selected tree }
I think that does it. I wouldn't recommend using a library for this kind though. Just define `TreePos` in your code and then write the functions that you happen to need.
On Wed, Jul 22, 2020 at 7:41 AM Dominik Schrempf < dominik.schrempf@gmail.com> wrote:
Hello Cafe!
I am trying to modify a large 'Data.Tree.Tree'. I managed to modify node labels with specific indices in the form of @[Int]@ as they are defined in, for example, 'Control.Lens.At.Ixed' or 'Lens.Micro.GHC'.
However, I also need to 1. modify the node label using information from nearby nodes (e.g., the children); 2. modify the tree structure itself; for example, I may want to change the sub-forest.
Basically, I need a lens that focuses not on the node label, but on the node itself. I perceived that this is more difficult.
I tried to use 'Control.Zipper'. I can use zippers to achieve point 1, albeit in a complicated way: (1) I need to go downwards to focus the specific node; (2) I need to traverse the children to collect data and save the data somewhere (how? in let bindings?); (3) I then go back upwards and change the node label using the collected data. Even so, I do not really manage to change the actual structure of the tree. I also briefly had a look at plates, but do not manage to use them in a proper way, maybe because the depth of my structures may be several hundred levels.
Did you encounter similar problems in the past or could you point me to resources discussing these issues?
Thank you! Dominik
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- -Andrew Thaddeus Martin
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Jeff Brown | Jeffrey Benjamin Brown Website https://msu.edu/~brown202/ | Facebook https://www.facebook.com/mejeff.younotjeff | LinkedIn https://www.linkedin.com/in/jeffreybenjaminbrown(spammy, so I often miss messages here) | Github https://github.com/jeffreybenjaminbrown

Thank you for the replies!
A specialized zipper suggested by Andrew Martin does the job quite well!
By the way, Control.Lens.Zipper, was factored out of lens into Control.Zipper in
newer versions.
Best,
Dominik
Jeffrey Brown
If you want an abstract solution, there's https://hackage.haskell.org/package/lens-3.2/docs/Control-Lens-Zipper.html.
On Wed, Jul 22, 2020 at 9:20 AM Jeff Clites via Haskell-Cafe < haskell-cafe@haskell.org> wrote:
Shouldn’t that be:
_before :: [TreePos a]
etc.?
Jeff
On Jul 22, 2020, at 4:54 AM, Andrew Martin
wrote: From containers, Tree is defined as:
data Tree a = Node { label :: a , children :: [Tree a] }
(I've renamed the record labels.) What is a zipper into such a tree? I think that the [rosezipper]( https://hackage.haskell.org/package/rosezipper-0.2/docs/Data-Tree-Zipper.htm... ) library gives a good definition. I'll specialized it to rose trees:
data TreePos a = Loc { _content :: Tree a -- ^ The currently selected tree. , _before :: [Tree a] -- ^ Forest to the left , _after :: [Tree a] -- ^ Forest to the right , _parents :: [([Tree a], a, [Tree a])] -- ^ Finger to the selected tree }
I think that does it. I wouldn't recommend using a library for this kind though. Just define `TreePos` in your code and then write the functions that you happen to need.
On Wed, Jul 22, 2020 at 7:41 AM Dominik Schrempf < dominik.schrempf@gmail.com> wrote:
Hello Cafe!
I am trying to modify a large 'Data.Tree.Tree'. I managed to modify node labels with specific indices in the form of @[Int]@ as they are defined in, for example, 'Control.Lens.At.Ixed' or 'Lens.Micro.GHC'.
However, I also need to 1. modify the node label using information from nearby nodes (e.g., the children); 2. modify the tree structure itself; for example, I may want to change the sub-forest.
Basically, I need a lens that focuses not on the node label, but on the node itself. I perceived that this is more difficult.
I tried to use 'Control.Zipper'. I can use zippers to achieve point 1, albeit in a complicated way: (1) I need to go downwards to focus the specific node; (2) I need to traverse the children to collect data and save the data somewhere (how? in let bindings?); (3) I then go back upwards and change the node label using the collected data. Even so, I do not really manage to change the actual structure of the tree. I also briefly had a look at plates, but do not manage to use them in a proper way, maybe because the depth of my structures may be several hundred levels.
Did you encounter similar problems in the past or could you point me to resources discussing these issues?
Thank you! Dominik
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- -Andrew Thaddeus Martin
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Nice timing, I was just reading Conal Elliott’s take on zippers [1][2] when you sent this question. It is interesting because it produces a concrete representation of the zippers via derivatives, like the manually constructed zippers, while still being completely generic*. I wonder if it is possible to combine the approach with lenses to get the same convenience while still being more concrete and flexible. Regards, Andreas [1]: http://conal.net/blog/posts/another-angle-on-zippers http://conal.net/blog/posts/another-angle-on-zippers [2]: http://hackage.haskell.org/package/functor-combo-0.3.6/docs/FunctorCombo-Zip... http://hackage.haskell.org/package/functor-combo-0.3.6/docs/FunctorCombo-Zip... * The library is sadly not implemented in terms of `GHC.Generics`, even though it uses the same combinators, since it predated it.
22 Jul 2020 kl. 13:40 skrev Dominik Schrempf
: Hello Cafe!
I am trying to modify a large 'Data.Tree.Tree'. I managed to modify node labels with specific indices in the form of @[Int]@ as they are defined in, for example, 'Control.Lens.At.Ixed' or 'Lens.Micro.GHC'.
However, I also need to 1. modify the node label using information from nearby nodes (e.g., the children); 2. modify the tree structure itself; for example, I may want to change the sub-forest.
Basically, I need a lens that focuses not on the node label, but on the node itself. I perceived that this is more difficult.
I tried to use 'Control.Zipper'. I can use zippers to achieve point 1, albeit in a complicated way: (1) I need to go downwards to focus the specific node; (2) I need to traverse the children to collect data and save the data somewhere (how? in let bindings?); (3) I then go back upwards and change the node label using the collected data. Even so, I do not really manage to change the actual structure of the tree. I also briefly had a look at plates, but do not manage to use them in a proper way, maybe because the depth of my structures may be several hundred levels.
Did you encounter similar problems in the past or could you point me to resources discussing these issues?
Thank you! Dominik
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
participants (5)
-
Andreas Källberg
-
Andrew Martin
-
Dominik Schrempf
-
Jeff Clites
-
Jeffrey Brown