RE: Endian mode and hPutBuf & hGetBuf

On Wednesday 08 January 2003 2:32 pm, Simon Marlow wrote:
Oops, I lied. hPutArray and hGetArray work on arrays of Word8 only, so in order to get non-portable results you need to use castIOUArray, which is already documented as having undefined behaviour.
I guess you must mean it's behaviour has not been defined yet. (Or is it's behaviour undefined by definition? :-)
I tried to use it recently to save an IOUArray of Word32's to a file by castIOUArray'ing it to an IOUArray of Word8's and using hPutArray (AFAICS the only possible way to do this using the current library functions).
It didn't work. For an array of N Word32's using N as the argument to hPutArray only gave me the first N/4 Word32's in the file. Using 4N gave me an error message about buffers. So I ended up not using an IOUArray at all :-(
That's a symptom of the bug that castIOUArray doesn't change the bounds of he array to reflect the new type, so hPutArray thinks you're trying to access the array outside its bounds. The trouble is, to do this properly we'd need to change the type of castIOUArray, so that it can get hold of the information it needs to rescale the bounds. Currently we have castIOUArray :: IOUArray ix a -> IO (IOUArray ix b) perhaps we'd need something like castIOUArray :: (C a, C b) => IOUArray ix a -> IO (IOUArray ix b) where C is some new class that lets you get at the scaling factors for the types a and b. 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? Cheers, Simon

On Thursday 09 January 2003 11:19 am, Simon Marlow wrote:
The trouble is, to do this properly we'd need to change the type of castIOUArray, so that it can get hold of the information it needs to rescale the bounds. Currently we have
castIOUArray :: IOUArray ix a -> IO (IOUArray ix b)
perhaps we'd need something like
castIOUArray :: (C a, C b) => IOUArray ix a -> IO (IOUArray ix b)
where C is some new class that lets you get at the scaling factors for the types a and b.
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?
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. 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). 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.) Also, as a minor niggle, I think the names should reflect the type of array in question. Something like hPutIOUArray instead of just hPutArray. 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 :-) Regards -- Adrian Hey
participants (2)
-
Adrian Hey
-
Simon Marlow