Если вы хотите использовать основную монаду монады трансформатора, вы можете использовать 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
Монада трансформаторы не «наслаиваются» в том смысле, что вы бы возвращать значение типа MyMonad MyType
изнутри; это более буквальное преобразование : превращают монаду в новую, которая имеет возможность запускать действия в преобразованной монаде. Итак, вы можете думать о StateT s m
как о обычной монаде State s
, за исключением того, что вы также можете использовать lift
для запуска действий поворота в m
в действия в StateT s m
.
Если вы используете стандартные Monad Transformer Library (MTL) трансформаторы, как StateT
, ReaderT
и т.д., вы на самом деле не использовать lift
; такие вещи, как modify
и ask
работают в любые монада с правым трансформатором где-то в стеке. (Стек просто башня трансформированных монад, как 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
здесь на самом деле не является функцией, более точный термин действие или вычисление.)
В случае, если вы не знаете о hoogle: HTTP: // www.haskell.org/hoogle – jberryman