IO behaves oddly if used nested

blaat blaat l4t3r at
Sat Oct 4 14:13:59 EDT 2003


>  Neither example is odd behavior, unless
>you consider Hugs providing a perfectly reasonable instance of Show for
>IO a odd.

True, every program behaves exactly as according to the definition of the 
run-time behavior of Haskell programs. (Hugs deviates a bit from ghc but ah 
well) The odd is not in the run-time behavior.

The odd is in the conceptual explanation. If I give a description of some f 
x = y function in Haskell I expect that some program f x is reduced to y and 
the result is given back (possibly printed). A good story to sell to 

This is almost everywhere the case except for the IO monad. In the former 
example, the inner putStr is _not_ evaluated but a message is shown (hinting 
that a IO has some structure we can observe before evaluation). In the 
latter example, it is shown that we are not interested in a result of a IO 
program, but only in its (lazily generated) side-effects. The monad behaves 
oddly with respect to the f x = y behavior.

I think I observe the following reactions when I explain IO:

1* Can't the guy in front of me stop poking his nose? (the blank faces and 
parse errors)
2* Hmm, feels like Java, looks like Java, ahah! is Java! (coders)
3* Hmm, feels like math, looks like math, ahah! is math! (designers and 

Group 1 will mimic, group 2 will produce obfuscuated Java code in Haskell, 
group 3 has great difficulty with the IO monad (although they are the first 
group who will write OK haskell programs) because it behaves differently 
from what they expect. The usual questions of group 3:

* Why is an IO a evaluated if I am not interested in it's result? (opposite 
to the f x = y lazy behavior)
* Why is in the putStr "hello world" example Hello World not shown? 
(opposite to expected f x = y eval-first-then-show behavior)
* Why is in the IO (IO ()) example the inner IO () not evaluated? (somewhat 
opposite to expected f (f x) behavior - I personally wonder if it is even 
sound in a category theoretical setting)
* ...Lots of other questions...

Hmm, have to finish this email now - time constraints. I guess the short 
story just is: IO monads == sometimes bad conceptual story to sell. 
Especially so since the "best" group has the biggest problems and 
non-trivial examples are only explainable in the end in terms of run-time 
behavior. What was that remark again about pointy headed people and Haskell? 

For that I also gave the Nomad datatype as a possible solution (needs a 
pretty hefty type checker though). A nice (old) idea would be to represent 
IO as programs which are interpreted by some _outside_ RTS in a given 
manner, and leave the Haskell language clean.
(It might even be a good idea with respect to the compiler implementation 
since it removes checking against unsafe IO behavior from the compiler -- 
just a thought)

Bye now, and cheers,

The new MSN 8: smart spam protection and 2 months FREE*

More information about the Haskell mailing list