On 04 October 2005 14:16, Duncan Coutts wrote:
On Tue, 2005-10-04 at 13:46 +0100, Malcolm Wallace wrote:
I wrote:
ghc: putChar _|_ -> _|_
hugs: putChar _|_ -> valid IO ()
I think it comes down to buffering behaviour doesn't it?
Having reviewed the IRC logs, I see I was talking nonsense.
You want to be able to store a closure for (putChar undefined) in a data structure, which seems like a perfectly reasonable thing to do. Provided the IO action is never actually run (after being retrieved from the data structure), the program really ought not to crash.
I see that nhc98 and hbc agree with Hugs on this behaviour, so ghc _must_ be wrong. :-)
Looking at GHC's library code we see that it is indeed forcing the char early:
hPutChar :: Handle -> Char -> IO () hPutChar handle c = c `seq` do ...
Fixed. However, I have a hunch that there are a *lot* of library functions whose strictness isn't completely specified by the report. Basically anything for which the report doesn't give the full code, except of course primitives which usually must be strict. This is only a hunch - I haven't actually gone looking for any. I suspect we get away with it most of the time because the desired strictness is "obvious" and/or the compilers all agree. Arguably, nothing returning IO should ever be strict, but you only have to use pattern matching in the implementation to violate that rule. Also, GHC's optimiser currently treats (_|_ :: IO a) and (do _|_; return ()) as interchangeable, which is naughty, and people have occasionally noticed, but the benefits can sometimes be huge. It is this distinction that makes it hard to optimise IO code in a Haskell compiler, though. Cheers, Simon