leftaroundabout
leftaroundabout

Reputation: 120711

How do you fmap a Getter?

As discussed on reddit, you can't just lift a Lens' a b to Lens' (Maybe a) (Maybe b). But for the special case Getter a b, this is obviously possible, since it's isomorphic to a->b. But unlike with Iso, there appears to be no standard function to perform this lift.

What's the preferred way to do that? In cases like

    someFunction $ myMap^.at(i).ꜰᴍᴀᴘGᴇᴛ(mySubGetter)

I could of course do

    someFunction $ myMap^.at(i) & fmap (^.mySubGetter)

but that doesn't work as well in other applications, as when operating on a state monad.

    foo <- use $ myMapInState.at(i).ꜰᴍᴀᴘGᴇᴛ(mySubGetter)

Upvotes: 4

Views: 415

Answers (1)

Reite
Reite

Reputation: 1667

I believe you can accomplish what you want with a prism.

If your values have these types:

myMap :: Map String (Int, String)
myMap = mempty

mySubGetter :: Lens' (Int, String) String
mySubGetter = _2

then you can do:

myVal :: Maybe String
myVal = myMap ^? at "myKey" . _Just . mySubGetter

If you just want to apply a function to a getter you can use the to function from Control.Lens.Getter, you have to manually deal with the sublens though:

someFunction $ myMap ^. at(i) . to (fmap (^. mySubGetter))

Upvotes: 4

Related Questions