Something I've wondered about: How does Haskell not optimize away IO ()? In a pure, functional languages, a function that doesn't return anything can simply be eliminated — but of course it isn't.<p>I've always assumed that Haskell's compiler has a built-in rules about IO having side effects, but I never actually bothered to find out.<p>When I first started with Haskell, one of many small epiphanies was when I realized that the IO monad itself doesn't actually <i>do</i> anything. bind and return don't do anything except wrap and unwrap values, and there's nothing that checks if you are in some kind of "IO context" to permit things like file I/O. There's no magical "side-effectful computation chain engine" behind the scenes.