lens creates a
Lens from a getter and a setter. The
resulting lens isn't the most effective one (because of having to
traverse the structure twice when modifying), but it shouldn't matter
much.
A (partial) lens for list indexing:
ix :: Int -> Lens' [a] a
ix i = lens (!! i) -- getter
(\s b -> take i s ++ b : drop (i+1) s) -- setter
Usage:
>>> [1..9] ^. ix 3
4
>>> [1..9] & ix 3 %~ negate
[1,2,3,-4,5,6,7,8,9]
When getting, the setter is completely unused; when setting, the
getter is unused. Both are used only when the value is being modified.
For instance, here we define a lens for the 1st element of a list, but
instead of a legitimate getter we use
undefined. Then we use
the resulting lens for
setting and it works, which proves that
the getter wasn't used:
>>> [1,2,3] & lens undefined (\s b -> b : tail s) .~ 10
[10,2,3]