Endian mode and hPutBuf & hGetBuf

Simon Marlow simonmar@microsoft.com
Mon, 13 Jan 2003 12:54:45 -0000

> Yes, this seems to be the real problem. To actually *do*=20
> anything sensible
> castIOUArray has to know the size of the types. Doesn't the Storable
> class give us this BTW?

The Storable class is almost the right thing, but not quite.  For
example, a UArray of Bool uses a bitmap whereas Storable.sizeOf (x ::
Bool) is probably 4.

> > This might be overkill.  Alternatively, castIOUArray could=20
> take the new
> > bounds as an argument, or we could have a way to replace=20
> the bounds of
> > an IOUArray/STUArray (unsafeReplaceBoundsIOUArray?).  Comments?
> Well I guess a simple hack would be to supply the size of the new type
> in bytes as an additional argument. (I assume the current size can be
> figured out from the current bounds and the No. of bytes allocated
> for the array.)
> But really, I think the function should be removed altogether because
> even if we sort this problem out it's still not portable (the effect
> of re-casting an array of Word32's as an array of Word8's will depend
> on the native endian mode). I would say once it's an array of Word32's
> it's always an array of Word32's.

It is non-portable and documented as such - however it does have its
uses (we use it in the compiler in a few places).  I considered giving
it an 'unsafe' prefix, and perhaps we should since you can currently
cause a crash by casting to an array of larger type and then writing off
the end.

Here are the options I see:

1. Change castIOUArray to take the new bounds as an argument.

   unsafeCastIOUArray :: (Ix i) =3D> IOUArray i e -> (i,i) -> IOUArray i =

   (rename to unsafeCastIOUArray, because it is certainly possible
   to cause a crash by giving inappropriate bounds).

2. Change castIOUArray to take the size of the new type as an
   argument (doesn't really work for Bools unless the "size" is
   in bits, and might be tricky in general because the size of
   array internally is always rounded up to a word boundary).

3. Define a separate class which allows us to get the
   appropriate scaling factor.

4. Add appropriate operations to the MArray class, and
   overload castIOUArray on MArray.

My opinion: (3) and (4) seem like overkill for an API which is still
non-portable (you need to know about representations in order to be able
to do anything sensible with castIOUArray, so you also know how to
rescale the bounds too), and I don't like (2) very much (see reasons
above).  That leaves (1).

> The only reason I wanted to re-cast in the first place is to write it
> to a file and the only function available demanded Word8's. That's
> why I think separate put/get functions for Word16's, Word32's,
> and Word64's are necessary. These functions should also require the
> endian mode to be specified explicitly (either by name or with an
> additional argument).

These are coming as part of the Binary library.

> An alternative might be to keep something like castIOUArray and
> demand that endian mode was specified explicitly there (and
> if that wasn't the native mode castIOArray would have to do
> the necessary juggling.)

You don't *have* to use castIOUArray here - you can always create a new
array explicitly for passing to hPutArray.  That would be completely
portable, too.

> Also, as a minor niggle, I think the names should reflect the type
> of array in question. Something like hPutIOUArray instead of just
> hPutArray.

Ok, I don't have any strong opinions here.  You can't "put" any other
types of arrays, though.

> My thoughts anyway. Perhaps this isn't the right way to go all.
> To be honest, I'm pretty confused about the bewildering variety
> of array's that seem to be available in Haskell/ghc and what you
> can and can't do with the various options on offer :-)=20

The trouble is that our arrays are parameterised over two features:
monadic vs. non-monadic (equivalently: mutable vs. non-mutable), and
boxed vs. unboxed.  It wasn't clear to me how to put these into the
module hierarchy - which feature should be higher up?  There are a
bewildering variety of possible layouts for the Data.Array hierarchy,
lots of which make sense.  I'd welcome feedback here - but I'm not sure
we'll reach an agreement easily.