As far as I know, seq a b
evaluates (forces) a
and b
before returning b
. It does not guarantee that a
is evaluated first.
pseq a b
evaluates a
first, then evaluates/returns b
.
Now consider the following:
xseq a b = (seq a id) b
Function application needs to evaluate the left operand first (to get a lambda form), and it can't blindly evaluate the right operand before entering the function because that would violate Haskell's non-strict semantics.
Therefore (seq a id) b
must evaluate seq a id
first, which forces a
and id
(in some unspecified order (but evaluating id
does nothing)), then returns id b
(which is b
); therefore xseq a b
evaluates a
before b
.
Is xseq
a valid implementation of pseq
? If not, what's wrong with the above argument (and is it possible to define pseq
in terms of seq
at all)?
The answer seems to be "no, at least not without additional magic".
The problem with
xseq a b = (seq a id) b
is that the compiler can see that the result of seq a id
is id
, which is strict everywhere. Function application is allowed to evaluate the argument first if the function is strict, because then doing so does not change the semantics of the expression. Therefore an optimizing compiler could start evaluating b
first because it knows it will eventually need it.