Search code examples
haskelliostatemonadsmonad-transformers

Why isn't IO an instantiation of State?


Why isn't IO an instantiation of the (strict) State monad when we have RealWorld, as provided in Control.Monad.ST? I thought RealWorld were meant to be a magical type representing the reality itself.

I mean, recall the "run" function of the State monad:

runState :: (s -> (a, s)) -> s -> a

Instantiating this to RealWorld, we get this:

runIO :: (RealWorld -> (a, RealWorld)) -> RealWorld -> a

Since we cannot construct a value of RealWorld anyway, this shouldn't act as a backdoor like unsafePerformIO.

Is the reason because this interpretation would enable the monad transformer IOT, defined as StateT RealWorld?


Solution

    1. Exposing the RealWorld in IO still gives you getUnsafePerformIO :: IO (IO a -> a) which is just as bad as unsafePerformIO.

    2. IO uses unlifted types (RealWorld#, (#,#)) to avoid unnecessary allocations, so it doesn't exactly match State anyway.

    3. It does match ST, but a direct definition of IO minimizes the noise whenever you look at Core or need to do some low level hacks (which are much more common than uses of ST that also involve IO).

    4. I thought RealWorld were meant to be a magical type representing the reality itself.

      RealWorld is a cute name but mostly a source of confusion. It really doesn't represent anything. It's best to forget RealWorld means anything and think of this definition of IO only in terms of operational semantics.