I'm the author of the instance [1].

One of my libraries uses Storable vectors to represent buffers of audio samples[1]. When the user doesn't need input, they leave the type of input vector to be `Vector ()`,
which is totally valid and reasonable under the constraint that the input buffer and the output buffer have the same size.

> This means that we can read an infinite number of ()
type values out of nothing (no memory location required) or store an
infinite number of () type values without even requiring a memory
location to write to.

Yes, we can read an infinite number of () without reading anything in memory. That's intended, and it is less arbitrary than defining () as a single byte object.

Perhaps you may want to reconsider the design of your array implementation before roasting this instance as "broken" and "absurd".

[1] https://gitlab.haskell.org/ghc/ghc/-/commit/97843d0b10cac3912a85329ebcb8ed1a68f71b34
[2] https://github.com/fumieval/bindings-portaudio/blob/4e49c50d19d141062e7a75a5e39d8c8388456309/System/PortAudio.hs#L252

2022年1月5日(水) 17:01 Harendra Kumar <harendra.kumar@gmail.com>:
The Storable instance of () is defined in the "Foreign.Storable"
module of the "base" package as follows:

instance Storable () where
  sizeOf _ = 0
  alignment _ = 1
  peek _ = return ()
  poke _ _ = return ()

The size of () is defined as 0. It sounds absurd for a Storable to
have a size of 0? This means that we can read an infinite number of ()
type values out of nothing (no memory location required) or store an
infinite number of () type values without even requiring a memory
location to write to.

This is causing a practical problem in our Storable array
implementation. The array is constrained to a Storable type. Since ()
has a Storable instance, one can store () in the Storable array. But
it causes a problem because we determine the array element size using
sizeOf on the type. For () type it turns out to be 0. Essentially, the
array of () would always be of size 0. Now, we cannot determine the
length of the array from its byte length as you could store infinite
such elements in an empty array. The Storable instance of () seems to
be an oddity and makes us use a special case everywhere in the code to
handle this, and this special casing makes it highly prone to errors
when we change code.

Can this be fixed? Is there a compelling argument to keep it like
this? A possible fix could be to represent it by a single byte in
memory which can be discarded when reading or writing. Another
alternative is to not provide a Storable instance for it at all. Let
the users write their own if they need it.

If you think this does not have a problem, can you suggest how to
elegantly handle the array implementation problem as I described
above?

Thanks,
Harendra
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries