这是我第一次认识 Monad Transformers,所以答案可能很明显。
假设我在 StateT MyMonad MyType 类型的 do 块中,我想让另一个相同类型的函数修改状态并返回 MyMonad MyType 类型的值。我怎样才能做到这一点?我想的例子here在 guessSession 中显示它,但我似乎无法理解如何应用它!
最佳答案
如果要在 monad 转换器中使用底层 monad,可以使用 lift
:
lift :: (MonadTrans t, Monad m) => m a -> t m a
在这种情况下,
t
是 StateT MyState
, 和 m
是 MyMonad
.因此,例如:foo :: StateT MyState MyMonad MyType
foo = do
modify $ \s -> s+1
lift $ doSomethingInMyMonad 42
Monad 转换器不是“分层”的,因为您将返回类型为
MyMonad MyType
的值。从内部;这是一种更直接的转换:他们将一个 monad 变成一个新的,能够在转换后的 monad 中运行操作。所以,你可以想到StateT s m
和普通的一样 State s
monad,除了你也可以使用 lift
在 m
中运行转弯 Action 进入行动 StateT s m
.如果您使用的是标准 Monad Transformer Library (mtl) 变压器,如
StateT
, ReaderT
等,您实际上不必使用 lift
;诸如 modify
和 ask
在堆栈中的某处使用正确的转换器在任何 monad 中工作。 (堆栈只是转换后的 monad 的塔,例如 StateT s (ReaderT r IO)
。)此外,如果你有一个大堆栈
IO
在底部,有一个提升IO
的便利功能。操作任意数量的层:liftIO :: (MonadIO m) => IO a -> m a
所以
liftIO (putStrLn "Hello, world!")
工作于 IO
, StateT Int IO
, ContT r (WriterT [String] IO)
, 等等。(作为附加说明,
foo
这里实际上不是函数;更准确的术语是 Action 或计算。)
关于haskell - monad 变压器内 monad 的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8943743/