使用Lens.Family.LensLike'作为状态计算中的setter和getter

Pav*_*vel 3 haskell lenses

我想在有状态计算中使用相同的镜头作为setter和getter.似乎GHC无法推断出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
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,是否有可能实现这样的行为,还是应该使用单独的镜头作为制定者和吸气剂?谢谢!

Boy*_*Jr. 5

几个选项在这里.首先,您可以使用RankNTypes,以便可以在每个"呼叫站点"使用不同的Functor实例,随后您可以将LensLike'用作getter和setter:

with :: (forall f. Functor f => LensLike' f s a) -> a -> State s b -> State s b
Run Code Online (Sandbox Code Playgroud)

其次,可能更好的是使用Lens'已经存在的类型 - 允许同时用作getter和setter.

with :: Lens' s a -> a -> State s b -> State s b
Run Code Online (Sandbox Code Playgroud)

您必须允许Functor从"呼叫站点"变为呼叫站点,因为选择特定的Functor会将镜头更改为getter或setter.Identity Functor用于设置,Const functor用于获取.