[Haskell-beginners] Re: Forcing evalation in the IO Monad

Stephen Blackheath [to Haskell-Beginners] mutilating.cauliflowers.stephen at blacksapphire.com
Fri Apr 16 15:14:54 EDT 2010


Philip Scott wrote:
> Daniel Fischer wrote:
>> Am Freitag 16 April 2010 16:25:08 schrieb Heinrich Apfelmus:
>>  
>>> Philip Scott wrote:
>>>    
>>>> What I want is something like putStrLn that doesn't print anything,
>>>> and takes any type as its input, evaluates it to normal form and then
>>>> does nothing else. It might be called something like 'evaluate' have a
>>>> type like this
>>>>
>>>> evaluate :: a -> IO()
>>>>       
>>> With Hoogle, you can search for types:
>>>
>>>    http://haskell.org/hoogle/?hoogle=a+-%3E+IO+%28%29
>>>
>>> 12th result from the top.
>>>     
>>
>> That evaluates only to WHNF.
>>
>> Control.DeepSeq.rnf seems to be closer, but requires NFData instances.
>>
>>   
> The documentation says that, but it does appear to go deeper than just
> one level:
> 
> Debug.Trace Prelude Control.Exception> let a = trace "Hello" 42
> Debug.Trace Prelude Control.Exception> let b = trace "Frank" (a * 2)
> Debug.Trace Prelude Control.Exception> evaluate b
> Frank
> Hello
> 84
> 
> Perhaps it specifies WHNF in case you 'evaluate' something which doesn't
> have a HNF (like a partially applied function?).

"evaluate x" is defined as "return $! x".  This indeed evaluates the
value immediately then and there.  It *only* evaluates to WHNF (weak
head normal form).  For number values, WHNF (= evaluate to outer
constructor only) and NF (= completely evaluate) are the same thing, as
shown in your example above.  The (a * 2) makes no difference, because
whether WHNF = NF or not depends on the type of the value only, not the
expression used to calculate it.

To evaluate x to NF (completely) then and there in general, you have to say

  evaluate (rnf x)

where rnf is defined in Control.DeepSeq in the 'deepseq' package.  The
type of x has to be an NFData instance.  Haskell does not provide any
other way to force evaluation to NF other than to explicitly use `seq`
on each element of the structure.  The purpose of DeepSeq is to make
this task easier.


Steve


More information about the Beginners mailing list