RE: Endian mode and hPutBuf & hGetBuf

Yes, this seems to be the real problem. To actually *do* 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 take the new bounds as an argument, or we could have a way to replace 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) => IOUArray i e -> (i,i) -> IOUArray i e (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 :-)
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. Cheers, Simon
participants (1)
-
Simon Marlow