Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Composing partial getters using the lens library

Tags:

haskell

lenses

I am using the lens package and and keep thinking there must be an easy solution to the following problem. Say I have some map (or any At instance) and a lens on its value type, ie

aMap :: Map Int a
aLens :: Simple Lens a b

I want a getter

g :: Getter (Map Int a) (Maybe b)

This is because I often want to do something like this

x :: Maybe b
x = aMap^.at 3.g.aLens

The intended semantics of course being that you get a Just value when you do so in the at lookup and Nothing otherwise.

When one is setting instead of getting traverse works in place of g, ie

newMap = at 3.traverse.aLens .~ whatever $ aMap

but not when you are getting. Is there some ready built in lens the library that I have simply missed, or is there another simple way of achieving this in a single expression?

like image 447
Vic Smith Avatar asked Apr 02 '13 20:04

Vic Smith


2 Answers

I've been running into a similar problem trying to compose lenses with at.

If you don't need the insertion/deletion behavior of at here, what about using ix?

x :: Maybe b
x = aMap ^? ix 3 . aLens
like image 135
jamesjb Avatar answered Oct 24 '22 23:10

jamesjb


I've managed to come up with

x :: Maybe b
x = aMap^.at 3 <&> (^.aLens)

which is a little confusing and not exactly what I was looking for, but gets the job done.

like image 35
Vic Smith Avatar answered Oct 25 '22 01:10

Vic Smith