
On Wed, 5 Jan 2022, Harendra Kumar wrote:
If we do not want to consume space for () then better not have a Storable instance for it, leave it to the users. And if we really want to store it then let it behave in the same way as any other mere mortal storable would, so what if it takes up some space. Why not have simple, uniform semantics for all cases? I think saving that extra byte for this particular case is an overkill and leading to a bigger cost in applications without actually saving anything worthwhile.
Maybe the Storable class is not the right one for your application. I came to this conclusion for my llvm-tf package for exchanging data between LLVM code and Haskell. Today I distinguish between base:Storable and my own LLVM.Storable class. They share implementations for Word8, Int16 and so on, but e.g. for Bool they differ (LLVM: one byte, base: four bytes) and LLVM.Storable supports tuples, whereas base:Storable does not. One of my LLVM applications works this way: I have an Arrow with existentially quantified state. If an arrow does not need a state, the state type is (). If I combine two arrows with (***) then I need to bundle their states in a pair. Thus I need to store () and I need to store nested tuples where some members are (). () is mapped to LLVM's empty tuple {}, and {} consumes no space. By using (***), the state type grows, but the required memory may stay the same. That is, () consuming no space can be very useful. However, that argument cannot be directly transfered to base:Storable, because base:Storable is not intended for tuples. If you find that your application needs tuples, then you better define your own Storable class, anyway.