I find myself using this pattern often:
do
let oldHeaders = mail ^. headers
put $ (headers .~ (insert header value oldHeaders)) mail
which seems like the kind of thing Control.Lens should be able to do, but I guess I just haven't found the right operator yet. Is there a better way? Also, is there anything else I should be doing differently in this code?
You can use a chain of Lens
es and Traversal
s to access the inner header value directly and update it.
put $ mail & headers . at header ?~ value
Note that (?~)
is just shorthand for \lens value -> lens .~ Just value
. The Just
is needed to indicate to the at
lens that we want to insert a value if it doesn't exist already.
If mail
in the first line comes from the state monad like this
do
mail <- get
let oldHeaders = mail ^. headers
put $ (headers .~ (insert header value oldHeaders)) mail
then it's simpler to write that with modify :: MonadState s m => (s -> s) -> m ()
modify (headers . at header ?~ value)
Which, as suggested by Ørjan Johansen in the comments, can be written most pithily as
headers . at header ?= value
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