|
|
|
|
|
by cousin_it
3949 days ago
|
|
There's no such thing as "the value IO ()". The type IO () has tons of possible values, which all have different internal representations: 1) The IO action that does nothing. 2) The IO action that prints the string "Hello World" and then returns nothing. 3) The IO action that reads a string from the console, reverses it, prints it back, and then returns nothing. 4) ... It's a common misconception to think that IO X is a wrapper around X with some "type system magic" to prevent it from being used outside IO. It's nothing like that. For example, IO String is not a wrapper around a String, doesn't contain any String inside, and cannot be converted to String. Meditate on the fact that System.IO.getLine is not a function, but a value of type IO String. Then you will understand why IO () has tons of possible values. |
|
Edit: I find it interesting that Haskell tutorials and books generally don't try to peel away some of Haskell's abstractions. Many texts will tell you that "IO a" represents an "action" and expect you to take this at face value, intead of explaining how this is distinguishable from a mere function, and how it's implemented internally. For example, I would say one of the big eureka moments for any Haskell learner is to realize how lazy-evaluated graphs of functions can turn into linearly-ordered programs thanks to the transparent "baton passing" of monad chaining (IO in particular). But I've yet to find a text which articulates this idea very well.
[1] http://stackoverflow.com/a/9244715/632555