Diciamo che ho un monadT:Perché non è necessario utilizzare 'lift' quando si interagisce con un monotT StateT nidificato in questo caso?
type Wrap a = ReaderT Env (StateT Int (StateT Int Identity)) a
La cosa importante da notare qui è che uno StateT è avvolgente altro, ed entrambi sono avvolti all'interno di una terza MonadT, vale a dire ReaderT.
e la funzione runWrap corrispondente per convenienza:
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
E un generico monade Stato tock:
tock :: (Num s, MonadState s m) => m()
tock = do modify (+1)
ora creare un monadT involucro al cui interno io uso tock:
aWrap :: Wrap (Int, Int)
aWrap = do
lift tock
lift . lift $ tock
x <- get
y <- lift . lift $ get
return (x, y)
ed eseguirlo:
env = Map.fromList [('x', 1)]
runWrap env 1 200 aWrap
// answer: (201,2)
L'uso di lift
qui ha senso per me in termini della mia comprensione di come interagire con layer nidificati di MonadT.
Tuttavia, questo funziona anche e mi danno la stessa risposta: (201,2)
:
aWrap :: Wrap (Int, Int)
aWrap = do
tock
lift . lift $ tock
x <- get
y <- lift . lift $ get
return (x, y)
penserei chiamando tock
w/o lift
, si legge come se tock
viene applicato al MonadT esterno, vale a dire ReaderT , il che non ha senso Ma perché funziona?
P.S. Si prega di ignorare la presenza di Env
qui, non ha nulla a che fare con la domanda, solo la scelta del Monade esterno che sto usando.