Question

Here's an extract from the documentation of evaluate:

Control.Exception.Base.evaluate :: a -> IO a
evaluate x

is not the same as

return $! x

A correct definition is

evaluate x = (return $! x) >>= return

(source)

These seem to have the same meaning. What is the difference between these two definitions?

Was it helpful?

Solution

Quick ref:

The type of evaluate is:

evaluate :: a -> IO a

seq has the type a -> b -> b. It firstly evaluates the first argument, then returns the second argument.

Evaluate follows these three rules:

evaluate x `seq` y    ==>  y
evaluate x `catch` f  ==>  (return $! x) `catch` f
evaluate x >>= f      ==>  (return $! x) >>= f

The difference between the return $! x and (return $! x) >>= return becomes apparent with this expression:

evaluate undefined `seq` 42

By the first rule, that must evaluate to 42.

With the return $! x definition, the above expression would cause an undefined exception. This has the value ⊥, which doesn't equal 42.

With the (return $! x) >>= return definition, it does equal 42.

Basically, the return $! x form is strict when the IO value is calculated. The other form is only strict when the IO value is run and the value used (using >>=).

See this mailing list thread for more details.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top