Результат монады внутри монадного трансформатора - PullRequest
5 голосов
/ 20 января 2012

Это мое первое знакомство с Monad Transformers, поэтому ответ может быть очевидным.

Допустим, я нахожусь внутри блока do типа StateT MyMonad MyType, я хочу сделать еще одну функцию того же типаизменить состояние и вернуть значение типа MyMonad MyType.Как я могу этого достичь?Я думаю, что примеры здесь показывают это в guessSession, но я не могу понять, как его применить!

1 Ответ

9 голосов
/ 20 января 2012

Если вы хотите использовать базовую монаду в преобразователе монад, вы можете использовать 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 здесь на самом деле не является функцией; более точный термин - action или вычисление .)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...