
dons:
nicolas.frisby:
I've noticed a few posts on the cafe, including my own experience, where the spine-strictness of the Binary instance for lists caused some confusion. I'd like to suggest an approach to preventing this confusion in the future, or at least making it easier to resolve.
Having decided that it is indeed appropriate for some standard instances to be strict by default [1], I think it would be beneficial to standardize an approach for expressing that a lazy instance is expected. I propose the following newtype be added to Data.Binary. A demonstration immediately follows.
newtype Lazily a = Lazily { unLazily :: a }
-- example instance instance Binary a => Binary (Lazily [a]) where -- lazy get and put
Now
[1..] = (unLazily . decode . encode . Lazily) [1..]
instead of
_|_ = (decode . encode) [1..]
This email is a request for comments on this concept. I think it is a minimal way of expressing the intent that the serialisation be lazy [2]. Please share any concerns or suggestions. I'll submit a patch once the discussion is complete... or if it becomes inactive ;)
I think this is a good compromise: allowing laziness for those who need it, in a clean manner. How about we provie
Data.Binary.Lazy
with the Lazy newtype, and lazy instances for types that make sense to be so?
For now, this can be developed as a single module depending on Data.Binary. What do you think, Nick?
I'd like to also use strictCheck, as we did for the stream fusion library, to state and check strictness properties for the instances, since getting this clear and correct seems to be a common FAQ with Binary. -- Don