[Haskell-cafe] Re: evaluate vs seq

Lennart Augustsson lennart at augustsson.net
Thu Sep 14 21:26:49 EDT 2006


On Sep 14, 2006, at 16:20 , apfelmus at quantentunnel.de wrote:

> Michael Shulman wrote:
>> On 9/13/06, apfelmus at quantentunnel.de <apfelmus at quantentunnel.de>  
>> wrote:
>>> So `seq` forces its first argument. When we define
>>>   f x = x `seq` (Return x)
>>> we thereby get
>>>   f _|_    == _|_
>>>   f []     == Return []
>>>   f (x:xs) == Return (x:xs)
>>> To compare, the semantics of (evaluate) is
>>>   evaluate _|_    == ThrowException =/= _|_
>>>   evaluate []     == Return []
>>>   evaluate (x:xs) == Return (x:xs)
>>> That should answer your question.
>>
>> I must not be phrasing my question very well; I feel like we're
>> talking past each other.  It seems to me that when writing actual
>> programs (rather than reasoning about denotational semantics) the
>> reason one would use `seq' or `evaluate' is to force something to be
>> evaluated "now" rather than "later", i.e. to get around Haskell's
>> default lazy execution.
>
>> Your semantics say that (x `seq` return x) and (evaluate x) have the
>> same result when x is anything other than _|_.  All well and good,  
>> but
>> (return x) *also* has those same results when x is not _|_.  Why  
>> would
>> one use the former two rather than (return x), if x is known not  
>> to be
>> _|_?  Because they evaluate x at different "times", right?  Even  
>> though
>> the eventual return value is the same, and thus the *semantics*  
>> are the
>> same.  So laying aside the formal semantics, what is the  
>> difference in
>> terms of actual, real, Haskell programs?
>
> You are right, I completely forgot that executing a real Haskell  
> program
> is a graph reduction and that `seq`'s purpose is to control this
> reduction and associated memory usage. But it's possible to use
> denotational semantics as an approximation to the actual graph  
> reduction.

No, you were right the first time. :)  The denotational semantics is  
the important one.  Haskell can be executed by other means than graph  
reduction.  (That's why the report says a "non-strict" rather than  
"lazy" language.)  Peculiar language constructs may allow you to tell  
the difference, but then they are highly dubious (and like all  
dubious things, they should be in the IO monad :) ).

	-- Lennart



More information about the Haskell-Cafe mailing list