This is my first acquaintance with Monad Transformers, so the answer might be obvious.
Let’s say I am inside a do block of type StateT MyMonad MyType, I want to make another function of the same type both modify the state and return a value of type MyMonad MyType. How can I achieve that? I think the examples here show it in guessSession, yet I can’t seem to understand how to apply it!
If you want to use the underlying monad in a monad transformer, you can use
lift:In this case,
tisStateT MyState, andmisMyMonad. So, for example:Monad transformers aren’t “layered on” in the sense that you’d return a value of type
MyMonad MyTypefrom inside; it’s a more literal transformation: they turn a monad into a new one that has the ability to run actions in the transformed monad. So, you can think ofStateT s mas just the regularState smonad, except that you can also useliftto run turn actions inminto actions inStateT s m.If you’re using the standard Monad Transformer Library (mtl) transformers like
StateT,ReaderT, etc., you don’t actually have to uselift; things likemodifyandaskwork in any monad with the right transformer somewhere in the stack. (A stack is just a tower of transformed monads, likeStateT s (ReaderT r IO).)Additionally, if you have a large stack with
IOat the bottom, there’s a convenience function for lifting anIOaction up any number of layers:So
liftIO (putStrLn "Hello, world!")works inIO,StateT Int IO,ContT r (WriterT [String] IO), and so on.(As an additional note,
foohere isn’t actually a function; a more accurate term is action or computation.)