Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I use lens in Haskell to duplicate Python's enumerate?

Python's enumerate on lists can be written as zip [0..]. I looked at Control.Lens.Traversal and Control.Lens.Indexed, but I couldn't figure out how to use lenses to generalize this to any reasonable container (I hesitate to say "Traversable").

I'm guessing itraverse or itraverseOf is key.

like image 589
Alex R Avatar asked Dec 03 '22 17:12

Alex R


1 Answers

If you're using a container that is an instance of FunctorWithIndex then you can simply use imap (,):

> imap (,) "abc"
[(0,'a'),(1,'b'),(2,'c')]

But if the index isn't the position this won't work:

> let m = Map.fromList [('a', "foo"), ('b', "bar"), ('c', "foobar")])
> imap (,) m
fromList [('a',('a',"foo")),('b',('b',"bar")),('c',('c',"foobar"))]

Instead you can use traversed, which is an indexed traversal where the index is the order the elements appear. This can be used for anything that's Traversable. Instead of imap use iover traversed (which is the same as imapOf but that's been deprecated):

> iover traversed (,) "abc"
[(0,'a'),(1,'b'),(2,'c')]

> iover traversed (,) m
fromList [('a',(0,"foo")),('b',(1,"bar")),('c',(2,"foobar"))]
like image 143
cchalmers Avatar answered Jan 18 '23 23:01

cchalmers