使用嵌套状态变换器修改可穿越镜头

时间:2017-09-09 01:07:08

标签: haskell monads lens

我有一个OuterState对象,其中包含多个_objects,应使用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

1 个答案:

答案 0 :(得分:1)

current_user.todos.first.is_owner?
在遍历use objects >>= traverse (execStateT nestedAction) >>= assign objects 字段期间,

object . traverse过于粗糙,无法优雅地表达count字段的更新(隐式来自nestedAction)。这基本上是镜头库没有运算符objects的原因:如果第二个参数修改了第一个参数中遍历所针对的状态部分,它就表现不佳。