Answers
- There are two reasons, one more practical and the other more principled:
- Firstly, lazy evaluation makes modeling I/O with ordinary functions practically unworkable. We lose the ability to reason compositionally about programs. Moreover, it is hard to figure out in what order I/O actions will happen, and this is crucial for program correctness.
- Secondly, pure functions (i.e., without I/O) have a number of essential properties (e.g., predictability and ease of reasoning) that Haskell wants to preserve. Adding I/O in the standard way would destroy that.
- Conceptually, we separate describing I/O actions from performing them. Haskell provides a type,
IO a
, that describes I/O actions that, when performed, yield a result of type a. It’s the job of the Haskell program’smain :: IO ()
function to construct such an I/O description, and the job of the runtime system to perform the I/O actions described.To create the
IO ()
description thatmain
should produce, the Haskell...