<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
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 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:
data IO a = IO MachineCode
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.