Every other monad comes with a transformer version, and from what I know the idea of a transformer is a generic extension of monads. Following how the other transformers are build, IOT would be something like
newtype IOT m a = IOT { runIOT :: m (IO a) }
for which I could make up useful applications on the spot: IOT Maybe can either do an IO action or nothing, IOT [] can build a list that can later be sequenced.
So why is there no IO transformer in Haskell?
(Notes: I’ve seen this post on Haskell Cafe, but can’t make much sense of it. Also, the Hackage page for the ST transformer mentions a possibly related issue in its description, but doesn’t offer any details.)
Consider the specific example of
IOT Maybe. How would you write aMonadinstance for that? You could start with something like this:Now you have
m' :: IO (Maybe (IO b)), but you need something of typeMaybe (IO b), where–most importantly–the choice betweenJustandNothingshould be determined bym'. How would that be implemented?The answer, of course, is that it wouldn’t, because it can’t. Nor can you justify an
unsafePerformIOin there, hidden behind a pure interface, because fundamentally you’re asking for a pure value–the choice ofMaybeconstructor–to depend on the result of something inIO. Nnnnnope, not gonna happen.The situation is even worse in the general case, because an arbitrary (universally quantified)
Monadis even more impossible to unwrap thanIOis.Incidentally, the
STtransformer you mention is implemented differently from your suggestedIOT. It uses the internal implementation ofSTas aState-like monad usingmagic pixie dustspecial primitives provided by the compiler, and defines aStateT-like transformer based on that.IOis implemented internally as an even more magicalST, and so a hypotheticalIOTcould be defined in a similar way.Not that this really changes anything, other than possibly giving you better control over the relative ordering of impure side effects caused by
IOT.