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 concepts are still the same.

The first type we’re going to look at is:

`type`

`Run`

`t`

`=`

`forall`

`n`

`o`

`b`

`.`

`(`

`Monad`

`n`

`,`

`Monad`

`o`

`,`

`Monad`

`(`

`t`

`o`

`))`

`=>`

`t`

`n`

`b`

`->`

`n`

`(`

`t`

`o`

`b`

`)`

That’s
incredibly dense, so let’s talk it out. The only “input” data type to this thing is t, a monad
transformer. A Run is a function that will then work with **any**
combination of types n, o, and b (that’s what the forall means). n and o are both monads,
while b is a simple value contained by them.

The lefthand side of the Run function, `t n b`

, is our ...

Start Free Trial

No credit card required