It's always said that Haskell's type system prevents impure code from polluting pure code, since you always have to specify IO
in the type signature. However, is that a consequence of the type system itself, or is it really just that IO(..)
isn't exported?
Basically, is it not true that, if the type constructor was available, something like this could be done?
ioToPure :: IO a -> a
ioToPure (IO ioValue) = ioValue
Yes, that is in a sense true.
The type system in and of itself doesn't know anything about IO
nor does it need to. It are different language features that hide the real representation of an IO action from the users, so that it is impossible to "just run" an IO action.
So, the truth is, that the IO security in Haskell and comparable languages is a combined result of several language features and properties, most prominently:
Nevertheless, I think that the expression "the type system makes sure that impure and pure code is separated" is a harmless simplification.