Use Lens as `map`
Asked Answered
J

2

8

I want to convert this line of code map (^?! ix 0) [[0, 1], [4, 5], [9, 1]] to entirely use lenses, so something like [[0, 1], [4, 5], [9, 1]] & each . ix 0. However, the types don't match up. What is the correct way to do this?

Joey answered 1/11, 2014 at 6:52 Comment(0)
G
10

Use folded:

Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] ^.. folded . ix 0
[0,4,9]

Works on any Foldable.

Also, if you plan to always extract the first element, perhaps it would be clearer to use the _head traversal from Control.Lens.Cons instead of ix.

[[0, 1], [4, 5], [9, 1]] ^.. folded . _head
Grainy answered 1/11, 2014 at 7:20 Comment(0)
K
10

You can use either of

Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] & each %~ (^?! ix 0)
[0,4,9]
Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] ^.. each . ix 0
[0,4,9]

The first corresponds to precisely what you wrote, using the unsafe (^?!) operator, which means that it can give an error. The second is safer by leaving out empty lists.

They work in somewhat different ways: The first creates a modified version of your original structure, which corresponds more to what map does, and it can be used on structures that aren't lists.

The second creates a list summary of your structure using the lens fold provided; although it can be used with many kinds of structures, the result is always a list.

You can also replace each by traverse (or, as @danidiaz points out, the slightly more general traversed) in this. The former works for many special things like tuples, while the latter works for any Traversable.

Kleeman answered 1/11, 2014 at 7:16 Comment(4)
Perhaps you mean traversed from Control.Lens.Traversal, instead of traverse?Grainy
@Grainy Nope, I mean traverse. Although it isn't from lens, it's considered an essential part of it.Landsman
@Grainy Oh I see, both work here. It seems traversed is more general, allowing indices.Landsman
I wasn't aware that one could use traverse directly. But looking at the type, I should have been.Grainy
G
10

Use folded:

Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] ^.. folded . ix 0
[0,4,9]

Works on any Foldable.

Also, if you plan to always extract the first element, perhaps it would be clearer to use the _head traversal from Control.Lens.Cons instead of ix.

[[0, 1], [4, 5], [9, 1]] ^.. folded . _head
Grainy answered 1/11, 2014 at 7:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.