
Malcolm Wallace wrote:
Simon Marlow
wrote: The difference is subtle. The semantics of seq and pseq are identical; however, GHC can see that seq is strict in both its arguments and hence could choose to evaluate them in either order, whereas pseq is only strict in its first argument as far as the strictness analyser is concerned. The point is that pseq is useful for controlling evaluation order, which is what you want for adding parallelism to a program. seq, on the other hand, is not useful for controlling evaluation order.
This is a rather weird thing, and I would consider it a bug in the Haskell Report, rather than a bug in ghc. (It bites hard when you are trying to implement something like HPC.)
The very name 'seq' surely suggests that you are controlling the evaluation order. "Please evaluate this thing on the left first". But that is _not_ what the Haskell Report says! Ghc takes the Report literally, and so the thing on the right is just as likely to be evaluated before the thing on the left!
The report is in general very careful to say absolutely *nothing* about evaluation order, leaving the implementation free to choose, either at compile time or possibly even runtime. This is an important principle, and something I feel quite strongly should be kept at the front of our minds for Haskell Prime. If it isn't already mentioned explicitly in the Haskell 98 report, I think it should be. Incedentally, this is also one reason I think lazy I/O is a wart (despite its obvious usefulness): because it necessarily requires talking about evaluation order. However, having said all that, arguably an exception should be made in this case. The main use of seq (and strictness annotations) is to control operational behaviour, rather than to change the semantics of the program - for example, it is most often used to prevent space leaks by "evaluating something earlier than it would otherwise be" (inverted commas because this isn't currently what seq actually does, as pointed out above). Indeed, if GHC was in the habit of causing the second argument of seq to be evaluated before the first, then a lot of people would probably be surprised. eg. imagine what happens to foldl': foldl' f a [] = a foldl' f a (x:xs) = let a' = f a x in a' `seq` foldl' f a' xs It wouldn't do what you want at all. So I'm agreeing with Malcolm, except that I believe that the evaluation-order property of seq should be a strong hint, not a requirement - otherwise we fall into the trap of mandating evaluation order. Cheers, Simon