On Wed, 2009-11-18 at 09:17 +0000, Simon Marlow wrote:
> So the main difference is that with the current formulation of deepseq,
> you need to explicitly force the result in order to use it, either with
> a pattern match, another seq, or a pseq. If we used (a -> b -> b) then
> the top-level forcing is "built-in".
>> Let's look at an example instance; here (1) is the current deepseq, (2)
> is deepseq :: a -> b -> b
>> instance (DeepSeq a, DeepSeq b) => DeepSeq (a,b) where
> -- (1) deepseq (a,b) = deepseq a `seq` deepseq b
> -- (2) deepseq (a,b) = deepseq a . deepseq b
>> They're both fairly similar. Most instances follow this pattern, with
> seq being replaced by (.).
>> You could argue that (a -> b -> b) is "doing more" than (a -> ()),
> because it has a kind of built-in continuation (Luke's point). I buy
> that, although (a -> ()) has a strange-looking unit type in the result
> and you have to use it in conjunction with seq.
I think the most important thing is to make the public interface that
people use most frequently simple and easy to remember.
Thus I suggest the primary function people use should be
deepseq :: DeepSeq a => a -> b -> b
because then all that users have to remember is:
"deepseq --- like seq but more so!"
That's it. Users already know how to use seq, so now they know how to
use deepseq too.
> (1) generates slightly better code with GHC, because it compiles seq
> directly into a case expression, whereas (.) involves a thunk. If
> deepseq is inlined all the way down, then it would turn into the same
> thing either way.
>> I don't feel terribly strongly, but I have a slight preference for the
> current version.
If it so happens that it is more convenient or faster to make the class
and instances use the (a -> ()) style then that is fine. We can give the
class method a different name. Presumably people have to write Deepseq
instances much less frequently than they use deepseq.
Duncan