[Haskell-cafe] GHC optimization changes evaluation strategy?

Chris Kuklewicz haskell at list.mightyreason.com
Tue Mar 13 07:40:48 EDT 2007


Dusan Kolar wrote:
> Hello all,
> 
>  the following program changes behavior if translated using different
> options for ghc compiler. Is this correct or not? I used The Glorious
> Glasgow Haskell Compilation System, version 6.6. And I would expect in
> both cases behavior 1.
> 
>  But I may be wrong...

You do not get to expect that unsafe* function are unaffected by optimizations.

> 
>  Thanks for any resolution.
> 
>  Dusan
> 
> 
> *Program:*
> 
> $ cat Test.hs
> import System.IO.Unsafe
> import System.IO
> 
> main = do
>  putStr "Start...\n"
>  putStr $ show $ falling' falling10000
>  putStr "\n"
>  putStr $ show $ sorted' rising10000
>  putStr "Stop...\n"
> 
> sorted' [] = True
> sorted' [_] = True
> sorted' l = sx l 1
>  where
>    sx []  _ = True
>    sx [_] _ = True
>    sx (x:l@(y:ys)) n =
>      if n==1000 then unsafePerformIO (putChar '.' >> hFlush stdout)
> `seq` x<=y && sx l 1
>      else x<=y && (sx l $! n+1)
> 
> falling' [] = True
> falling' [_] = True
> falling' l = sx l 1
>  where
>    sx []  _ = True
>    sx [_] _ = True
>    sx (x:l@(y:ys)) n =
>      if n==1000 then unsafePerformIO (putChar '.' >> hFlush stdout)
> `seq` x>=y && sx l 1
>      else x>=y && (sx l $! n+1)
> 
> rising10000 = [0..100000]
> 
> falling10000 = [100000,99999..0]
> 
> -- EOF
> 

the expression

> unsafePerformIO (putChar '.' >> hFlush stdout)

has type "()" and does not depend on anything in scope. The `seq` command
demands that this be evaluated to see it is bottom or the value "()", but then
it never needs to be re-evaluated, as Haskell may assume it is will be immutably
the value "()".

> 
> 
> *Behavior 1:*
> 
> $ ghc Test.hs -o test
> $ ./test
> Start...
> ....................................................................................................True
> 
> ....................................................................................................TrueStop...

There it is re-evaluated.

> 
> 
> 
> *Behavior 2:*
> 
> $ rm test Test.o Test.hi
> $ ghc -O2 Test.hs -o test
> $ ./test
> Start...
> .True
> .TrueStop...
> 

There it is evaluated once and cached.


More information about the Haskell-Cafe mailing list