It is a little difficult to use stacks StateTbecause it becomes confusing as to which layer you are talking to when you write getor put. If you use an explicit style stack transformers, you need to use a bunch lift, and if you use a class mtl-based class method , you are completely stuck.
type Z a = StateT Int (StateT String IO) a
go :: Z ()
go = do int <- get
str <- lift get
replicateM int (liftIO $ putStrLn str)
We could avoid this mess with an explicit type of product condition. Since we derive functions from our product state for each individual component, it is easy to getinsert into those individual components usinggets
data ZState = ZState { int :: Int, str :: String }
type Z a = StateT ZState IO a
go :: Z ()
go = do i <- gets int
s <- gets str
replicateM i (liftIO $ putStrLn s)
: (1) put, (2) int , str. .
lens -savvy, zoom
-- the real type is MUCH more general
zoom :: Lens' mother child -> StateT child m a -> StateT mother m a
"" . , , :
data ZState = ZState { _int :: Int, _str :: String }
makeLenses ''ZState
type Z = StateT ZState IO a
inc :: MonadState Int m => m ()
inc = modify (+1)
yell :: MonadState String m => m ()
yell = modify (map toUpper)
go :: Z ()
go = do zoom int $ do inc
inc
inc
zoom str yell
i <- use int
s <- use str
replicateM i (liftIO $ putStrLn s)
- zoom in , inc yell . get use.
, zoom zoom , .
type Z a = EitherT String (ListT (StateT ZState IO)) a
>>> :t zoom int :: EitherT String (ListT (StateT Int IO)) a -> Z a
zoom int :: EitherT String (ListT (StateT Int IO)) a -> Z a
, zoom , . ( , , , , .)