<div dir="auto">I don't think it's broken; I think your length calculation is broken. Instead of asking every use of () to take an extra byte, why don't you just store a word saying how long your array is?<div dir="auto"><br></div><div dir="auto">Alternatively, you could probably avoid special cases with a newtype:<div dir="auto"><br></div><div dir="auto">newtype NZS a = NZS { unNZS :: a }</div><div dir="auto"><br></div><div dir="auto">instance Storable a => Storable (NZS a) where</div><div dir="auto"> sizeof</div><div dir="auto"> | sizeof (undefined @a) == 0</div><div dir="auto"> = const 1</div><div dir="auto"> | otherwise = sizeof .# unNZS</div><div dir="auto"> alignment = alignment .# unNZS</div><div dir="auto"> peekElemOff = coerce (peekElemOff @a)</div><div dir="auto"> ....</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jan 5, 2022, 3:01 AM Harendra Kumar <<a href="mailto:harendra.kumar@gmail.com">harendra.kumar@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The Storable instance of () is defined in the "Foreign.Storable"<br>
module of the "base" package as follows:<br>
<br>
instance Storable () where<br>
sizeOf _ = 0<br>
alignment _ = 1<br>
peek _ = return ()<br>
poke _ _ = return ()<br>
<br>
The size of () is defined as 0. It sounds absurd for a Storable to<br>
have a size of 0? This means that we can read an infinite number of ()<br>
type values out of nothing (no memory location required) or store an<br>
infinite number of () type values without even requiring a memory<br>
location to write to.<br>
<br>
This is causing a practical problem in our Storable array<br>
implementation. The array is constrained to a Storable type. Since ()<br>
has a Storable instance, one can store () in the Storable array. But<br>
it causes a problem because we determine the array element size using<br>
sizeOf on the type. For () type it turns out to be 0. Essentially, the<br>
array of () would always be of size 0. Now, we cannot determine the<br>
length of the array from its byte length as you could store infinite<br>
such elements in an empty array. The Storable instance of () seems to<br>
be an oddity and makes us use a special case everywhere in the code to<br>
handle this, and this special casing makes it highly prone to errors<br>
when we change code.<br>
<br>
Can this be fixed? Is there a compelling argument to keep it like<br>
this? A possible fix could be to represent it by a single byte in<br>
memory which can be discarded when reading or writing. Another<br>
alternative is to not provide a Storable instance for it at all. Let<br>
the users write their own if they need it.<br>
<br>
If you think this does not have a problem, can you suggest how to<br>
elegantly handle the array implementation problem as I described<br>
above?<br>
<br>
Thanks,<br>
Harendra<br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank" rel="noreferrer">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div>