Powiedzmy mam monadT:Dlaczego w tym przypadku nie musisz używać "windy" podczas interakcji z zagnieżdżoną StateT monadT?
type Wrap a = ReaderT Env (StateT Int (StateT Int Identity)) a
Ważne jest, aby pamiętać, jest to, że jeden StateT jest owijanie drugiego, a oba są owinięte wewnątrz trzeciego MonadT, mianowicie ReaderT.
i odpowiednia funkcja runWrap dla wygody:
type Env = Map.Map Char Integer
runWrap :: Env -> Int -> Int -> Wrap a -> a
runWrap env st1 st2 m = runIdentity $ evalStateT (evalStateT (runReaderT m env) st2) st1
a generycznego monady państwowej tock:
tock :: (Num s, MonadState s m) => m()
tock = do modify (+1)
I teraz utworzyć monadT oblewania gdzie wewnątrz używam tock:
aWrap :: Wrap (Int, Int)
aWrap = do
lift tock
lift . lift $ tock
x <- get
y <- lift . lift $ get
return (x, y)
Uruchom go:
env = Map.fromList [('x', 1)]
runWrap env 1 200 aWrap
// answer: (201,2)
Użycie tutaj lift
ma dla mnie sens pod względem zrozumienia sposobu interakcji w/zagnieżdżonych warstwach MonadT.
Jednak ta działa również i daj mi tę samą odpowiedź: (201,2)
:
aWrap :: Wrap (Int, Int)
aWrap = do
tock
lift . lift $ tock
x <- get
y <- lift . lift $ get
return (x, y)
Myślę wywołując tock
w/o lift
, to brzmi jakby tock
jest stosowany do zewnętrznej MonadT, mianowicie ReaderT , co nie ma sensu. Ale dlaczego to działa?
P.S. Proszę zignorować obecność Env
tutaj, nie ma nic wspólnego z pytaniem, po prostu wybór zewnętrznej Monady, której używam.