2012-01-20 4 views
5

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

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

+1

В случае, если вы не знаете о hoogle: HTTP: // www.haskell.org/hoogle – jberryman

ответ

9

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

+0

Думаю, я понимаю. Просто чтобы быть совершенно ясным. Представьте, что я сделал <- doSomethingInMyMonad 42 перед добавлением StateT. Теперь я делаю <- lift $ doSomethingInMyMonad 42. Правильно? – aelguindy

+0

@aelguindy: Да! Если у вас есть раздел кода, который просто использует 'MyMonad', вы также можете снять целый блок do:' lift $ do ...'. – ehird

+0

Спасибо! Не уверен, что это правильное место, чтобы спросить, но есть ли эквивалент лифта, но с двумя аргументами, lift2? * Глупый вопрос! * Нашел ответ – aelguindy

Смежные вопросы