
On 18/11/2009 03:48, Dean Herington wrote:
At 11:00 AM +0000 11/17/09, Simon Marlow wrote:
I've just uploaded deepseq-1.0.0.0 to Hackage
http://hackage.haskell.org/package/deepseq
This provides a DeepSeq class with a deepseq method, equivalent to the existing NFData/rnf in the parallel package. I'll be using this in a newly revamped parallel package, which I hope to upload shortly.
Cheers, Simon
The documentation claim that "The default implementation of 'deepseq' is simply 'seq'" is not exactly right, as `deepseq` and `seq` have different signatures. Which raises the more interesting question: Why did you choose a different signature? And, would a version of `seq` with the same signature as `deepseq` be useful?
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. (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. Cheers, Simon