您正在使用
use
在
ASetter
但是
Getter
:
use :: MonadState s m => Getting a s a -> m a
(.=) :: MonadState s m => ASetter s s a b -> b -> m ()
不幸地
和
Getting
type Getting r s a = (a -> Const r a ) -> s -> Const r s
type ASetter s t a b = (a -> Identity b) -> s -> Identity t
Const
和
Identity
任意地。我们需要一个
Lens
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
请注意,没有
f
在左侧。接下来,我们注意到您的
lift
没有必要。毕竟
f
已经在我们的目标单子中工作
m
举起
modifyObjects
是在
IO
和
action
是在
StateT Game IO
m
:
modifyingM :: MonadState s m => Lens s s a a -> (a -> m b) -> m ()
modifyingM l f = do
old <- use l
new <- f old
l .= old
真管用!但这可能是错误的,因为您可能想要设置
新
中的值
l .= old
. 如果是这样,我们必须确保
old
new
具有相同类型:
-- only a here, no b
-- v v v v
modifyingM :: MonadState s m => Lens s s a a -> (a -> m a) -> m ()
modifyingM l f = do
old <- use l
new <- f old
l .= new
举起
尽管如此:
action :: StateT Game IO ()
action = modifyingM objects (lift . modifyObjects)
类型Lens s t a b=forall f。函子f=>(a->f b)->s->f.t
对于任何
a -> f b
s -> f t
. 因此,如果我们只是在你的对象中插入一些东西,我们有
> :t \f -> objects f
\f -> objects f
:: Functor f => (GameObject -> f GameObject) -> Game -> f Game
因此,我们只需要一些
MonadState s m => (s -> m s) -> m ()
import Control.Monad.State.Lazy (get, put) -- not the Trans variant!
modifyM :: MonadState s m => (s -> m s) -> m ()
modifyM f = get >>= f >>= put
注意,您需要使用
Control.Monad.State
从…起
mtl
而不是
Control.Monad.Trans.State
put :: Monad m => s -> StateT s m ()
和
get :: Monad m => StateT s m s
MonadState
mtl公司
如果我们把所有的东西放在一起,我们就会看到
modifyingM
modifyingM :: MonadState s m => Lens s s a a -> (a -> m a) -> m ()
modifyingM l f = modifyM (l f)
l f
:
modifyingM :: MonadState s m => Lens s s a a -> (a -> m a) -> m ()
modifyingM l f = use l >>= f >>= assign l