GHC -O2 and unsafePerformIO

Duncan Coutts duncan.coutts at
Wed May 2 12:06:12 EDT 2007

On Wed, 2007-05-02 at 16:33 +0100, Neil Mitchell wrote:
> Hi
> Thanks to dcoutts, I have now come up with an answer. I don't
> understand why it works now, but not before.

main = p_System_IO_hGetChar 1
 `seq` p_System_IO_hGetChar 2
 `seq` putStrLn "done"

This is fine (though note that p_System_IO_hGetChar 1 is a constant) the
real problem is here:

{-# NOINLINE p_System_IO_hGetChar #-}
p_System_IO_hGetChar h   = trace "i am here" $
    unsafePerformIO $ 
      getchar >>= \c -> 
      print c >>
      return (if c == (-1) then 0 else chr_ c)

You've tried to trick ghc into always calling this by passing a dummy
'h' parameter. Then 'h' is never used in the body. Note however that the
whole body of this function is a constant and so ghc can (and at -O2
does) float it out as a CAF. This means you get the side effects of
p_System_IO_hGetChar at most once.

The solution of course is to use a full data dependency like IO or ST

> I do remember than browsing either Core or STG is not a fun thing to
> do...

So yeah, we see the above CAFs and let floating by looking at the core.
We could do with a prettier pretty printer for core, I agree.


More information about the Glasgow-haskell-users mailing list