[Haskell-cafe] ANN: generic-deepseq

Bas van Dijk v.dijk.bas at gmail.com
Thu Feb 23 23:24:23 CET 2012

On 23 February 2012 22:09, Maxime Henrion <mhenrion at gmail.com> wrote:
> On Sun, 2012-02-19 at 21:06 +0100, Bas van Dijk wrote:
>> On 19 February 2012 18:11, Maxime Henrion <mhenrion at gmail.com> wrote:
>> > I'm guilty of not having preserved the "rnf :: a -> ()"
>> > function as the class function though, it's a wrapper around "deepseq"
>> > in my code. I just didn't see the point of having a class function with
>> > such a signature versus having a function just like "seq :: a -> b ->
>> > b". In retrospect, that might have been a bad idea, and maybe I should
>> > switch to have an "rnf :: a -> ()" class function to make switching even
>> > easier?
>> I'm not sure but maybe a method like "rnf :: a -> ()" is easier to optimize.
>> Also in my experience (with generics support in aeson and cereal) it's
>> a very good idea (performance-wise) to INLINE your methods like I did
>> in my previous message. Of course the only way to know for sure is the
>> create some (criterion) benchmarks.
> Well I wrote some dumb criterion benchmarks that run deepseq over
> increasingly bigger lists of numbers, and it appears that using rnf as
> the member function of the DeepSeq class indeed makes a _huge_
> difference.

Nice, that's what I expected. Have you checked if adding INLINE
pragma's helps even more? (I guess not since it's already on par with
manual written code, as you mentioned)

BTW I would also recommend making a benchmark for a big sum type.

Some nitpicking:

* In the instance:

instance GDeepSeq U1 where grnf _ = ()

I think it makes sense to pattern match on the U1 constructor, as in:
grnf U1 = ().

I haven't checked if that's necessary but my fear is that assuming:
data Unit = Unit deriving Generic; instance DeepSeq Unit
rnf (⊥ :: Unit) would equal: () while I would expect it to equal ⊥.

* Why do you have the instance:

instance GDeepSeq V1 where grnf _ = ()

The only way to construct values of a void type is using ⊥. And I
would expect that rnf ⊥ = ⊥, not (). I think the best thing is to just
remove the V1 instance.



More information about the Haskell-Cafe mailing list