I have some datatypes along the line of
data Outer = Outer { _list :: [ Inner ] }
data Inner = Inner { _bool :: Bool }
using Control.Lens, I can access the _bool of the ith Inner (inside a 'State Outer' monad) like this
boolValue <- gets (^. list . to (!! i) . inner)
I would like to also be able to update this value with something like
list ^. (to (!! i)) ^. inner %= True
However (by my understanding), the 'to' function only creates a getter, not a true lens that can be used as either getter or setter.
So, how can I convert (!! i) into a lens that will allow me to update this field?
You can't* turn (!!)
into any lens-like thing other than a Getter
-- but there's a function to do this sort of thing: ix, for accessing things at indices. It's actually a Traversal
, not a Lens
-- which, here, just means that it can fail (if the index is out of bounds) -- but as long as the index is in the list, it'll work.
There's another problem, though -- (^.)
is also an operator that's used exclusively for getting values. It's incompatible with e.g. (%=)
, which takes a lens-like thing as its first argument. And: (%=)
is for mapping a function over the existing value; if you just want to set, you can use (.=)
. So you probably want something like:
list . ix i . inner .= True
* There actually is a function that can do this -- it's called upon
-- but it uses wonderful evil black magic and you shouldn't use it, at least not for this (and probably not for any real code).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With