Use Lens.Family.LensLike 'as setter and receiver in state calculations

I would like to use the same lens as setter and getter inside stateful computation. And it looks like GHC can't infer generic type for Functor f.

import Lens.Family
import Lens.Family.State
import Control.Monad.State

-- | Run computation inside modified state
with :: Functor f => LensLike' f s a -> a -> State s b -> State s b
with lens value comp = do
  value' <- use lens
  lens .= value
  res <- comp
  lens .= value'
  return res

      

So my question is, is it possible to achieve this behavior, or use separate lenses for the setter and getter? Thank!

+3


source to share


1 answer


A couple of options here. First, you can use RankNTypes so that each "call site" can use a different Functor instance, after which you can use LensLike "as both a receiver and a setter:

with :: (forall f. Functor f => LensLike' f s a) -> a -> State s b -> State s b

      

Second, and probably better, use a type Lens'

that is already existential, which allows it to be used as both a getter and a setter.



with :: Lens' s a -> a -> State s b -> State s b

      

You must allow the Functor to vary from a "call site" to a site, as the choice of a particular Functor is what changes the lens to getter or setter. The identity functor is used for customization, the Const functor is used to get it.

+5


source







All Articles