Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.
This is the entire pattern of monad-control: we embed the extra features of our monad transformer inside the value. Once in the value, the type system ignores it and focuses on the inner monad. When we're done playing around with that inner monad, we can pull our state back out and reconstruct our original monad stack. Types I purposely started with the ErrorT transformer, as it is one of the simplest for this inversion mechanism. Unfortunately, others are a bit more complicated. Take for instance, ReaderT. It is defined as newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a } . If we apply runReaderT to it, we get a function that returns a monadic value. So we're going to need some extra machinery to deal with all that stuff. And this is when we leave Kansas behind. There are a few approaches to solving these problems. In the past, I implemented a solution using type families in the neither package. Anders Kaseorg implemented a much more straightforward solution in monad-peel . And for efficiency, in monad-control , Bas van Dijk uses CPS (continuation passing style) and existential types. The code taken from monad-control actually applies to version 0.2.0.3 changed things just a bit, by making the state explicit with an associated type, and generalizing MonadControlIO to MonadBaseControl , but the con- cepts are still the same.