
On Mon, Mar 7, 2011 at 3:38 PM, Alexander Solla
This can be detected by seq: the left-hand side doesn't terminate, whereas
the right-hand side does. And moreover, this can mess up other things (e.g., monads) by introducing too much laziness. Space leaks are quite a serious matter and they have nothing to do with trying to compare uncomputable values. Do you want a seemingly insignificant refactoring to cause your program to suddenly hang forever? Or to take up gobs more space than it used to?
'seq' is not a "function", since it breaks referential transparency and possibly extensionality in function composition. By construction, "seq a b = b", and yet "seq undefined b /= b". Admittedly, the Haskell report and the GHC implementation, diverge on this issue. Haskell98 specifically defines seq in terms of a comparison with bottom, whereas GHC "merely" reduces the first argument to WHNF. In any case, the reduction is a side effect, with which can lead to inconsistent semantics if 'seq' is included in "the language".
It is nice to know that we can work in a consistent language if we avoid certain constructs, such as 'seq', 'unsafePerformIO', and probably others. In addition to making the "core language" conceptually simpler, it means that we can be sure we aren't inadvertently destroying the correctness guarantees introduced by the Howard-Curry correspondence theorem.
As a matter of fact, if you read GHC.Prim, you will see that seq is a bottom! seq :: a -> b -> b seq = let x = x in x The "magic" semantics of evaluating the first argument are done by the compiler/runtime, and are apparently not expressible in Haskell. This is true of inline lazy unsafeCoerce and dozens of others, all of which are expressed as specialized types with the same equation: let x = x in x