On Thu, 2012-02-23 at 23:24 +0100, Bas van Dijk wrote: > On 23 February 2012 22:09, Maxime Henrion <mhenr...@gmail.com> wrote: > > On Sun, 2012-02-19 at 21:06 +0100, Bas van Dijk wrote: > >> On 19 February 2012 18:11, Maxime Henrion <mhenr...@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)
Oh, I had forgotten to mention that: INLINE pragmas indeed didn't make any significant difference in my tests, so I let them out. > BTW I would also recommend making a benchmark for a big sum type. Yes, I should definitely do that. > 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 ⊥. That's a good point, I will do tests to see whether this makes a difference. This seems to mirror my thinking when I asked you whether it would be safe to skip seq calls in the case the constructor of a type is strict in another e-mail (have you seen it?). > * 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. This would have the consequence that any type tagged with a phantom type (for whatever reason) couldn't be used with deepseq, it would return bottom. What if I want to deepseq a 2-3 finger tree tagged with a type-level natural that ensures the proper shape of the tree statically? It seemed to me that I should be able to do that; this is why I added this V1 instance. Cheers, Maxime
signature.asc
Description: This is a digitally signed message part
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe