Serge D. Mechveliani mechvel at botik.ru
Tue Oct 12 01:45:35 EDT 2004

On Mon, Oct 11, 2004 at 04:35:30PM +0100, Simon Peyton-Jones wrote:
> Ah I see.  You get earlier results, but the overall computation is
> unchanged. 
> Hmm.  I can't say I'm persuaded.  The transformation is unsound in
> general and, because it makes programs lazier, it'll slow programs down
> a bit; in exchange there's the possibility of earlier output (which may
> or may not be visible in the ultimate result).
> I think you are better off writing the program you want, rather than
> relying on the compiler to find it for you!

I am sorry, there was a typo. 
The `else' branch should contain 'c' instead of 'b': 

  main = hSetBuffering stdout NoBuffering >> putStr (out "\n")
  out :: String -> String
  out = let valueTakingLong =  last [1 .. (10^8)]  > 0
        if  valueTakingLong  then ('a' :) . ('b' :)
        else                      ('a' :) . ('c' :)

(as you note, it has some sense even with the typo).

Also here is an example of 1000 times speed up by factoring `if':

  main = putStr (f:"\n")

  f :: Char  
      head (if valueTakingLong then  'a': "b"  else  'a': "c")

   -- head ('a': (if valueTakingLong then "b" else "c"))
Factoring `if' means un-commenting the last line.
And further, such factoring leads to the complile-time 
transformation  f --> 'a'.

These two examples are very artificial.
Why does not the programmer define directly  f = 'a'  ?
The real program is like this:

  prove :: Goal -> ProofResult
  prove g =
       res'   = prove (deriveFrom g)  :: ProofResult
       trace' = pTrace res'
                -- recurse, obtain res' and add something to
                -- some fields of  res' 
    case (foo g, foo' g)
    (A, _) -> res' {...    = ...,
                    pTrace = ('a' :) . ('b' :) . trace'
                   }                             :: ProofResult
    (_, B) -> res' {...    = ...,
                    pTrace = ('a' :) . ('c' :) . trace'
    _      -> ...
And  pTrace  prints out not `lazily': one needs to wait 1 hour
instead of immediately observing the first members of the final 
The effect is the same as of 1000 times slow down. Because in many 
cases it is sufficient to observe the first steps and to find out
what to improve.

The intention was: "compute it as in the factored `case' form".
And now I need to rewrite it in such a form.
It takes effort to find out how to write this in a natural way, 
while the initial program did not require any effort to write. 

Generally, what I fear of is a  hidden slow down.

In the above case it was easy to detect the effect, because it 
shouted on the print-out.
But it may occur that many other fragments contain the slow downs
of 10-20 times caused by the reasons like unfactored `if', 
and they are hard to discover, because they do not shout on the 
Though, I have not any convincing example, so far.

Serge Mechveliani
mechvel at botik.ru

More information about the Glasgow-haskell-users mailing list