Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I traverse different parts of data structure one after the other?

In Control.Lens.Traversal the beside function traverses both parts of a Bitraversable. The example given is

>>> ("hello",["world","!!!"])^..beside id traverse
["hello","world","!!!"]

Can I write a more explicit version of beside (let's call it bothParts) that instead of a Bitraversable constraint takes two Traversals? I imagine it to be used like so:

>>> ("hello",["world","!!!"])^..bothParts _1 _2 id traverse
["hello","world","!!!"]

Does this already exist? Is this too unsafe to be sanely used? Thank you!

Edit:

Or perhaps something like:

>>> ("hello",["world","!!!"])^..bothParts _1 (_2.traverse)
["hello","world","!!!"]
like image 783
phischu Avatar asked Oct 31 '22 23:10

phischu


1 Answers

The combinator you want is supposed to use 2 Traversals simultaneously. But that kind of combinator breaks Traversal laws in general, in particular the "no duplication" law: a Traversal should traverse each element only once.

Here's an example of what you probably don't want:

>>> (1, 2) ^.. bothParts _1 _1
[1, 1]    

To be more precise, I'd like to cite Traversal documentation from lens package:

The laws for a Traversal t follow from the laws for Traversable as stated in "The Essence of the Iterator Pattern".

t pure ≡ pure
fmap (t f) . t g ≡ getCompose . t (Compose . fmap f . g)

One consequence of this requirement is that a Traversal needs to leave the same number of elements as a candidate for subsequent Traversal that it started with. Another testament to the strength of these laws is that the caveat expressed in section 5.5 of the "Essence of the Iterator Pattern" about exotic Traversable instances that traverse the same entry multiple times was actually already ruled out by the second law in that same paper!

like image 148
fizruk Avatar answered Nov 15 '22 08:11

fizruk