Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Traversal over last element of 'filtered'

I'm looking to filter a traversal, then select the last element to use with over.

e.g. something like this (but which will actually compile):

[1,2,3,4] & traverse . filtered even . _last +~ 10
> [1,2,3,14]

Any ideas?

P.S. I'm aware that filtered is only valid when not affecting the number of elements in the traversal.

The actual use case I'm performing is to select only the lowest level of a recursive uniplate traversal that matches some predicate; if you have other ideas of how to do this I'd love to hear them!

like image 946
Chris Penner Avatar asked Jun 19 '17 02:06

Chris Penner


2 Answers

This isn't really an answer, just a follow-up to @Gurkenglas that's too big for a comment. Note that @Gurkenglas's answer:

let t = partsOf (traverse . filtered even) . _last

may look like a Traversal, but it isn't, even if you maintain the element count, because it violates the second Traversal law (for obvious reasons):

let f = Identity . succ
[1,2,3,4] & fmap (t f) . t f  -- yields [1,3,3,5] effectively
[1,2,3,4] & getCompose . t (Compose . fmap f . f)
                              -- yields [1,2,3,6] effectively

For it to be a traversal, you have to maintain both the element count and the filtering property as invariants.

Whether this will matter for your application, I don't know, but just be aware that partsOf comes with these sorts of caveats, and the documentation misleadingly suggests that the result of partsOf will be a Lens if you maintain the element count. (That's true for partsOf each, the example given in the documentation, but not in general.)

like image 121
K. A. Buhr Avatar answered Sep 29 '22 13:09

K. A. Buhr


[1,2,3,4] & partsOf (traverse . filtered even) . _last +~ 10
like image 39
Gurkenglas Avatar answered Sep 29 '22 12:09

Gurkenglas