使用嵌套状态转换器修改可移动镜头
Modify a traversable lens using a nested state transformer
我有一个包含多个 _objects
的 OuterState
对象,应该使用 nestedAction
对其进行修改,这也需要访问 OuterState
对象。因此,nestedAction
是一个嵌套状态转换器,每个 InnerStateObject
是 运行,如本例所示:
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Control.Lens ((+=), makeLenses)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.State.Lazy
(StateT, evalStateT, execStateT, get)
import Control.Monad.Trans.Class (lift)
data OuterState = OuterState
{ _objects :: [InnerStateObject]
, _count :: Int
} deriving (Show)
data InnerStateObject = InnerStateObject
{ _value :: Int
} deriving (Show)
makeLenses ''OuterState
makeLenses ''InnerStateObject
startNestedAction :: StateT OuterState IO ()
startNestedAction = do
get >>= liftIO . putStrLn . ("before: " ++) . show
objects . traverse <~% execStateT nestedAction
get >>= liftIO . putStrLn . ("after: " ++) . show
nestedAction :: StateT InnerStateObject (StateT OuterState IO) ()
nestedAction = do
value += 10
lift $ count += 100
main :: IO ()
main =
evalStateT
startNestedAction
OuterState {_count = 0, _objects = map InnerStateObject [0 .. 2]}
本例中缺少 <~%
的定义。优先级为infixr 2 <~%
。它应该将 objects . traverse
的每个值传递给 execStateT nestedAction
并将结果分配给 objects . traverse
.
如何实施 <~%
?它的类型是什么?
依赖项: lts-9.3
use objects >>= traverse (execStateT nestedAction) >>= assign objects
object . traverse
粒度太粗,无法在 objects
字段的遍历期间优雅地表达 count
字段的更新(通过 nestedAction
隐式)。这基本上就是镜头库没有运算符 (<~%) :: MonadState s m => ATraversal' s a -> (a -> m a) -> m ()
的原因:如果它的第二个参数修改了第一个参数中遍历的目标状态部分,它就不会表现良好。
我有一个包含多个 _objects
的 OuterState
对象,应该使用 nestedAction
对其进行修改,这也需要访问 OuterState
对象。因此,nestedAction
是一个嵌套状态转换器,每个 InnerStateObject
是 运行,如本例所示:
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Control.Lens ((+=), makeLenses)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.State.Lazy
(StateT, evalStateT, execStateT, get)
import Control.Monad.Trans.Class (lift)
data OuterState = OuterState
{ _objects :: [InnerStateObject]
, _count :: Int
} deriving (Show)
data InnerStateObject = InnerStateObject
{ _value :: Int
} deriving (Show)
makeLenses ''OuterState
makeLenses ''InnerStateObject
startNestedAction :: StateT OuterState IO ()
startNestedAction = do
get >>= liftIO . putStrLn . ("before: " ++) . show
objects . traverse <~% execStateT nestedAction
get >>= liftIO . putStrLn . ("after: " ++) . show
nestedAction :: StateT InnerStateObject (StateT OuterState IO) ()
nestedAction = do
value += 10
lift $ count += 100
main :: IO ()
main =
evalStateT
startNestedAction
OuterState {_count = 0, _objects = map InnerStateObject [0 .. 2]}
本例中缺少 <~%
的定义。优先级为infixr 2 <~%
。它应该将 objects . traverse
的每个值传递给 execStateT nestedAction
并将结果分配给 objects . traverse
.
如何实施 <~%
?它的类型是什么?
依赖项: lts-9.3
use objects >>= traverse (execStateT nestedAction) >>= assign objects
object . traverse
粒度太粗,无法在 objects
字段的遍历期间优雅地表达 count
字段的更新(通过 nestedAction
隐式)。这基本上就是镜头库没有运算符 (<~%) :: MonadState s m => ATraversal' s a -> (a -> m a) -> m ()
的原因:如果它的第二个参数修改了第一个参数中遍历的目标状态部分,它就不会表现良好。