此解决方案对镜头查看的状态执行操作
objects . traverse . num .=>> putStrLn . ("num: " ++) . show
例子:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
module Main where
import Control.Monad.IO.Class
import Control.Lens
-- (Getting, Lens', LensLike', lens, makeLenses, view, zoom)
import Control.Lens.Internal.Zoom -- (Focusing)
import Control.Monad.Trans.State.Lazy -- (StateT(StateT), execStateT)
viewM :: Monad m => Getting t s t -> (t -> m a) -> StateT s m a
viewM g f = StateT $ \s -> (, s) <$> f (view g s)
viewEachM ::
Monad m => LensLike' (Focusing m c) t s -> (s -> m c) -> StateT t m c
viewEachM g f = zoom g $ id .=> f
infix 4 .=>, .=>>
(.=>) :: Monad m => Getting t s t -> (t -> m a) -> StateT s m a
g .=> f = viewM g f
(.=>>) :: Monad m => LensLike' (Focusing m c) t s -> (s -> m c) -> StateT t m c
g .=>> f = viewEachM g f
data GameObject = GameObject
{ _num :: Int
} deriving (Show)
data Game = Game
{ _objects :: [GameObject]
} deriving (Show)
makeLenses ''Game
makeLenses ''GameObject
defaultGame = Game {_objects = map GameObject [0 .. 3]}
action :: StateT Game IO ()
action = do
id .=> putStrLn . ("game: " ++) . show
objects .=> putStrLn . ("objects: " ++) . show
objects .=> putStrLn . ("length of objects: " ++) . show . length
-- use .=>> as alternative
objects .=>> putStrLn . ("length of objects: " ++) . show . length
-- if you use traverse you have to use .=>>
objects . traverse . num .=>> putStrLn . ("num: " ++) . show
main :: IO ()
main = do
execStateT action defaultGame
return ()
输出:
game: Game {_objects = [GameObject {_num = 0},GameObject {_num = 1},GameObject {_num = 2},GameObject {_num = 3}]}
objects: [GameObject {_num = 0},GameObject {_num = 1},GameObject {_num = 2},GameObject {_num = 3}]
length of objects: 4
length of objects: 4
num: 0
num: 1
num: 2
num: 3
解析器: lts-9.3