Question

I have a deeply nested data structure, and I'm using Control.Lens.* to simplify accessing its values in a state monad.

So consider the following:

data Config = Config { _foo :: Maybe Int
                     , _bar :: Int
                     }

$(makeLenses ''Config)

How do I operate "functorially" over the Maybe? I'd like to write an idiomatic getter that does:

config = Config (Just 1) 0
config^.foo.to fmap (+1) == Just 2

Better still, how would we handle the case when Config is nested deeper?

data Config = { _foo :: Maybe Foo }
data Foo = Foo { _bar :: Bar }
data Bar = Bar Int
$(makeLenses ''Bar)
$(makeLenses ''Foo)

Can we use the accessors foo and bar to Maybe return a modified Bar?

Was it helpful?

Solution

You'll want to use a Prism to (maybe) go into the the Just branch.

>>> let config' = config & foo . _Just .~ (+1)
    in  config' ^. foo
Just 2

And then this Prism will compose just the same as other lenses, forming Traversals.

foo . _Just . bar . _Bar :: Traversal' Config Int

Take a look at some tutorials I wrote on lens that spend a little time examining how Lens and Prism relate:

https://www.fpcomplete.com/user/tel/a-little-lens-starter-tutorial

https://www.fpcomplete.com/user/tel/lens-aeson-traversals-prisms

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top