
On Tuesday 13 January 2009 7:27:10 pm Luke Palmer wrote:
When GHC starts optimizing (Writer Builder) as well as it optimizes PutM, then that will be a cogent argument. Until then, one might argue that it misses "the whole point of Put".
Well it can still serve as an optimization over bytestrings using whatever trickery it uses (I am assuming here -- I am not familiar with its trickery), the same way DList is an optimization over List. It's just that its monadiness is superfluous.
Surely PutM and Writer Put have almost the same performance?! (I am worried if not -- if not, can you give an indication why?)
The underlying monoid is Builder. The point of PutM is to be a version of Writer that's specialized to the Builder monoid for maximum performance. It looks like: data PairS a = PairS a {-# UNPACK #-} !Builder newtype PutM a = Put { unPut :: PairS a } I'm not sure why it's split up like that. Anyhow, the strict, unpacked Builder gets optimized better than Writer Builder. Even if you change Writer to: data Writer w a = Writer a !w it still won't match up, because polymorphic components don't get unpacked and such. That's, for instance, why Data.Sequence uses a specialized version of the finger tree type, instead of using the general version in Data.FingerTree. Only exposing Put as a monoid is kind of redundant. You might as well work straight with Builder. -- Dan