What is happening?
The reason this is happening to you is that if you look at the type of Lens'
:
type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s
That is essentially giving you the ability to trade in a Lens'
at any one choice of Functor f
you want. However, use
wants to pick Accessor a
, while .=
wants to pick Mutator
.
How to do what you asked
If you are passed a Lens
and want to use it multiple times with different choices of functor, you'll need to either
a.) pass it with a higher rank type
{-# LANGUAGE RankNTypes #-}
foo :: MonadState a m => Lens' a b -> m ()
foo p = do
use p
p .= undefined
b.) cloneLens
it before you use it for reading and/or writing.
:t \p -> do{use (cloneLens p); cloneLens p.=undefined}
Using cloneLens
at each side will make a consistent choice of Functor, generating a fresh lens each time.
c.) Use the combinators from Control.Lens.Loupe
.
:t \p -> do gets (^# p); p #= undefined
These are designed to always make the same kind of choice as cloneLens
would.
How to do what you probably want
In practice, it is better to use another approach, like
:t \p -> p %= \oldValue -> newValue
as this will support any Traversal
or Setter
, not just a Lens
, opening you up to more usecases.
If you need to get the value out for future calculations:
:t \p -> p %%= \oldValue -> (whatYouWantToReadFromIt, whatYouWantToWriteToIt)