What is inside Haskell IO?

<lambdabot> shachaf says: getLine :: IO String contains a String in the same
way that /bin/ls contains a list of files

There are multiple ways IO could be implemented internally. Here’s a demonstration of one.

MiniIO (below) implements an ADT of arbitrarily chosen primitives that represent I/O operations and a way to combine them. One can create, evaluate and manipulate MiniIO values without causing any side effects to occur. That is what example in Main.hs does. The same applies to real IO values in Haskell: you can create a big list of print "hello"s and later pick which ones to actually execute.

You can have an IO action executed by assigning it to main. If the actual IO is implemented like MiniIO, the runtime system will run an interpreter against the value main and execute the appropriate impure effects. This is simulated by running runMiniIO against example. runMiniIO doesn’t actually contain impurity but instead simulates standard input and output as pure strings and a trivial filesystem as a pure map from filename to contents.

Another hypothetical implementation of Haskell IO might be based on:

dataIOa=IOMachineCode

This one highlights how an IO String does not contain a String but a description of how to generate one. GHC uses yet another implementation (which doesn’t involve interpreting an ADT in runtime). The semantics and the API from the point of view of you the programmer are the same for all of them.