2012-01-20 19 views
5

Este es mi primer contacto con Monad Transformers, por lo que la respuesta puede ser obvia.Resultado de la mónada dentro del transformador de mónada

Digamos que estoy dentro de un bloque do de tipo StateT MyMonad MyType, quiero hacer que otra función del mismo tipo modifique el estado y devuelva un valor de tipo MyMonad MyType. ¿Cómo puedo lograr eso? Creo que los ejemplos here lo muestran en guessSession, ¡pero parece que no puedo entender cómo aplicarlo!

+1

En caso de que usted no sabe acerca de Hoogle: http: // www.haskell.org/hoogle – jberryman

Respuesta

9

Si desea utilizar la mónada subyacente en un transformador mónada, puede utilizar lift:

lift :: (MonadTrans t, Monad m) => m a -> t m a 

En este caso, es tStateT MyState y m es MyMonad. Así, por ejemplo: transformadores

foo :: StateT MyState MyMonad MyType 
foo = do 
    modify $ \s -> s+1 
    lift $ doSomethingInMyMonad 42 

Monad no están "en capas sobre" en el sentido de que le devuelve un valor de tipo MyMonad MyType desde el interior; es una transformación más literal : convierten una mónada en una nueva que tiene la capacidad de ejecutar acciones en la mónada transformada. Por lo tanto, puede pensar en StateT s m como la mónada normal State s, excepto que también puede usar lift para ejecutar acciones de giro en m en acciones en StateT s m.

Si está utilizando los Monad Transformer Library transformadores (MTL) como estándar StateT, ReaderT, etc., que no realmente tiene que usar lift; cosas como modify y ask funcionan en cualquiera mónada con el transformador correcto en algún lugar de la pila. (Una pila es sólo una torre de mónadas transformadas, como StateT s (ReaderT r IO).)

Además, si usted tiene una gran pila con IO en la parte inferior, hay una función de conveniencia para el levantamiento de una acción IO cualquier número de capas:

liftIO :: (MonadIO m) => IO a -> m a 

así liftIO (putStrLn "Hello, world!") obras en IO, StateT Int IO, ContT r (WriterT [String] IO), y así sucesivamente.

(Como nota adicional, foo aquí no es realmente una función, un término más preciso es acción o cálculo .)

+0

Creo que entiendo. Solo para ser perfectamente claro. Imagine que hice un <- doSomethingInMyMonad 42 antes de agregar StateT. Ahora hago un <- lift $ doSomethingInMyMonad 42. ¿Correcto? – aelguindy

+0

@aelguindy: ¡Sí! Si tiene una sección de código que simplemente usa 'MyMonad', también puede levantar un bloque do completo:' levantar $ do ... '. – ehird

+0

Gracias! No estoy seguro si este es el lugar correcto para preguntar, pero ¿hay un equivalente para levantar pero con 2 argumentos, levantar2? * ¡Pregunta estúpida! * Encontré la respuesta – aelguindy

Cuestiones relacionadas