I've had a bit of difficulty using Lenses with Maps. I have maps that look like this Map String (Map String Int)
. These are multidimensional arrays, and I usually set them up with known dimensions. I often want to read and update elements of these Maps, but not add or delete elements.
I want an optic, similar to ix "k1" . ix "k2"
that allowed me to do the following:
myfunc :: Map String (Map String Int) -> ()
myfunc m =
let m' = m & ix "k1" . ix "k2" %~ (+1)
v = m ^. ix "k1" . ix "k2"
in ()
Unfortunately, I can't use ix "k1" . ix "k2"
because the v = m ^. ix "k1" . ix "k2"
won't compile because Int
isn't a Monoid. In general, I can't have this Monoid restriction because I generally hold fairly complex values in my maps (like some complex state ADT). (I'm guessing this Monoid restriction is there so that ix
can return a default value if the key doesn't exist.) I want an optic without this Monoid restriction and that would just throw a fatal error if I try indexing with a key that doesn't exist. Is it possible to create such a thing on my own?
(^?)
or(^?!)
? – Bridges^.
^?!
works for my purposes! I didn't realize I had this degree of freedom. – FuentesMonoid
to combine results of a traversal.(^?!)
takes only the first result, so there's no need to combine, so noMonoid
constraint.(^?)
wraps it in aMaybe
, as there may in fact be no results at all. – Bridges