
Hello, I have two questions about the array APIs in the libraries: 1. Is there a way to write an immutable array to a handle without using any unsafe methods? 2. Why does the function 'getBounds' (of the 'MArray' class) return its result in a monad? -Iavor

Iavor Diatchki wrote:
Hello, I have two questions about the array APIs in the libraries:
1. Is there a way to write an immutable array to a handle without using any unsafe methods?
In what format? There is no canonical form for an IArray except for Show/Read. If you mean "can I treat the array as a large block of bytes as dump that to a handle?" then you need Data.Array.IO.hPutArray and hGetArray. Or possibly Data.Array.Storable with Foreign.Marshal.Array might help.
2. Why does the function 'getBounds' (of the 'MArray' class) return its result in a monad?
It is so that mutable arrays which dynamically change their bounds can be supported.

Hello Chris, Wednesday, November 15, 2006, 8:46:47 PM, you wrote:
1. Is there a way to write an immutable array to a handle without using any unsafe methods?
If you mean "can I treat the array as a large block of bytes as dump that to a handle?" then you need Data.Array.IO.hPutArray and hGetArray. Or possibly Data.Array.Storable with Foreign.Marshal.Array might help.
and unboxed arrays, of course
2. Why does the function 'getBounds' (of the 'MArray' class) return its result in a monad?
It is so that mutable arrays which dynamically change their bounds can be supported.
arrayref library contains implementation of dynamic arrays that can be easily ported to using Base library primitives -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Hello,
On 11/15/06, Chris Kuklewicz
Iavor Diatchki wrote:
Hello, I have two questions about the array APIs in the libraries:
1. Is there a way to write an immutable array to a handle without using any unsafe methods?
In what format? There is no canonical form for an IArray except for Show/Read. I should have been more clear. I was thinking of an array of bytes, and I was wondering if there is a function like 'hPutArray' from Data.IO.Array that works on immutable arrays (e.g, ordinary Haskell arrays, or unboxed immutable arrays of bytes). Using 'hPutArray' is not good in this case because to turn an immutable array into a muttable one we have to copy it.
2. Why does the function 'getBounds' (of the 'MArray' class) return its result in a monad?
It is so that mutable arrays which dynamically change their bounds can be supported. There do not appear to be methods in the MArray class that allow arrays to change their bounds...
-Iavor

Iavor Diatchki wrote:
Hello,
On 11/15/06, Chris Kuklewicz
wrote: Iavor Diatchki wrote:
Hello, I have two questions about the array APIs in the libraries:
1. Is there a way to write an immutable array to a handle without using any unsafe methods?
In what format? There is no canonical form for an IArray except for Show/Read. I should have been more clear. I was thinking of an array of bytes, and I was wondering if there is a function like 'hPutArray' from Data.IO.Array that works on immutable arrays (e.g, ordinary Haskell arrays, or unboxed immutable arrays of bytes). Using 'hPutArray' is not good in this case because to turn an immutable array into a muttable one we have to copy it.
In general, the IArray interface supports many data layouts and semantics for the instances. The standard Haskell Array is lazy where each item in the array can be a thunk; therefore there is no contiguous series of bytes in memory to send to a handle. There are IArray instances that do have such layouts in memory: Data.Array.Storable has such a layout and you can get the Ptr: withStorableArray :: StorableArray i e -> (Ptr e -> IO a) -> IO a which can be combined with System.IO's hPutBuf :: Handle -> Ptr a -> Int -> IO () to define (using Foreign.Storable's sizeOf): hPutStorableArray :: Handle -> StorableArray i e -> IO () hPutStorableArray h arr = withStorableArray arr (\ptr -> hPutBuf h (sizeOf arr)) Alternatively you can use Data.MArray's unsafeThaw (in GHC at least) to turn an array of type UArray into an IOUArray WITHOUT MAKING A COPY and then use Data.Array.IO's hPutArray: hPutUArray :: Handle -> UArray i e -> IO () hPutUArray h u'arr = do iou'arr <- unsafeThaw u'arr iou'arr'bytes <- castIOUArray iou'arr hPutArray h iou'arr'bytes where the castIOUArray is needed to change the element type to Word8. I have not tested the above, so there are probably a few errors.
2. Why does the function 'getBounds' (of the 'MArray' class) return its result in a monad?
It is so that mutable arrays which dynamically change their bounds can be supported. There do not appear to be methods in the MArray class that allow arrays to change their bounds...
True: There are MArray instances that cannot change their size, therefore the MArray class does not specify those operations are available. It have merely been changed to accommodate them by making getBounds monadic. See http://haskell.org/haskellwiki/Library/ArrayRef#Reimplemented_Arrays_library for (possibly dynamically) resizable instances. Cheers, Chris

Hello Chris, Friday, November 17, 2006, 1:51:07 PM, you wrote:
http://haskell.org/haskellwiki/Library/ArrayRef#Reimplemented_Arrays_library for (possibly dynamically) resizable instances.
dynamically, dynamically. array automatically grows when written to non-existent position and can be resized explicitly by resizeDynamicArray -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Hello, I am aware of the unsafe methods to cast arrays. My question was if there was a function in the libraries to dump an immutable array of bytes to a handle, that is safe (it could, of course, be implemented behind the scene using unsafe primitives, however, this is implementation specific). My impression was that there isn't one, and I guess you are confirming this. I think it would be useful to have such a function in the libraries.
There do not appear to be methods in the MArray class that allow arrays to change their bounds...
True: There are MArray instances that cannot change their size, therefore the MArray class does not specify those operations are available. It have merely been changed to accommodate them by making getBounds monadic.
See http://haskell.org/haskellwiki/Library/ArrayRef#Reimplemented_Arrays_library for (possibly dynamically) resizable instances.
I was not aware of this, thanks for the reference. I need to look at it more closely, but didn't this decision remove an important point in the design space, namely mutable arrays of a fixed size? I would imagine these are quite important when you care about managing resources. I guess the monadic 'getBounds' still supports them but it looses some type information... -Iavor

Iavor Diatchki wrote:
Hello,
I am aware of the unsafe methods to cast arrays. My question was if there was a function in the libraries to dump an immutable array of bytes to a handle, that is safe (it could, of course, be implemented behind the scene using unsafe primitives, however, this is implementation specific). My impression was that there isn't one, and I guess you are confirming this. I think it would be useful to have such a function in the libraries.
That is right. In GHC, the "array of bytes" is mutable: either a Ptr or a StorableArray. The UArray is implemented as an immutable "array of bytes" but you cannot get the Ptr to this without unsafeThaw. But since hPutUArray does not use the IOUArray to write to memory this is actually safe, and hGetUArray forgets the IOUArray so it is safe:
import System.IO import Data.Word import Data.Array.Unboxed import Data.Array.IO
hPutUArray :: Handle -> UArray Int Word8 -> IO () hPutUArray h u'arr = do iou'arr <- unsafeThaw u'arr let (a,b) = bounds u'arr hPutArray h iou'arr (b-a+1)
hGetUArray :: Handle -> (Int,Int) -> IO (UArray Int Word8) hGetUArray h bnds@(a,b) = do iou'arr <- newArray_ bnds let len = b-a+1 len' <- hGetArray h iou'arr len if len/=len' then fail $ "Not enough bytes from handle:" ++ show (len,len') else unsafeFreeze iou'arr
where this time I actually loaded up the code and made it compile. So you now have your IArray of bytes: the UArray instance.
There do not appear to be methods in the MArray class that allow arrays to change their bounds...
True: There are MArray instances that cannot change their size, therefore the MArray class does not specify those operations are available. It have merely been changed to accommodate them by making getBounds monadic.
See http://haskell.org/haskellwiki/Library/ArrayRef#Reimplemented_Arrays_library
for (possibly dynamically) resizable instances.
I was not aware of this, thanks for the reference. I need to look at it more closely, but didn't this decision remove an important point in the design space, namely mutable arrays of a fixed size? I would imagine these are quite important when you care about managing resources. I guess the monadic 'getBounds' still supports them but it looses some type information...
-Iavor

iavor.diatchki:
Hello,
I am aware of the unsafe methods to cast arrays. My question was if there was a function in the libraries to dump an immutable array of bytes to a handle, that is safe (it could, of course, be implemented behind the scene using unsafe primitives, however, this is implementation specific). My impression was that there isn't one, and I guess you are confirming this. I think it would be useful to have such a function in the libraries.
If its arrays of bytes only you're working with, you might use Data.ByteString. Malcolm found it to be a bit faster than UArrays of Word8, if I recall, and it has lots of IO operations. -- Don

Iavor Diatchki wrote:
I am aware of the unsafe methods to cast arrays. My question was if there was a function in the libraries to dump an immutable array of bytes to a handle, that is safe (it could, of course, be implemented behind the scene using unsafe primitives, however, this is implementation specific). My impression was that there isn't one, and I guess you are confirming this. I think it would be useful to have such a function in the libraries.
It's true that there isn't a way to write an arbitrary UArray to a Handle as a sequence of bytes, but there is also no requirement that a UArray is even implemented as a sequence of bytes either; indeed the Hugs implementation doesn't represent a UArray using unboxed elements. If we were to add a way to serialise a UArray to a Handle, we'd also have to specify the exact serialised representation (or leave it undefined). Cheers, Simon

Hello Simon, Monday, November 20, 2006, 3:44:16 PM, you wrote:
implemented as a sequence of bytes either; indeed the Hugs implementation doesn't represent a UArray using unboxed elements.
really? :) data UArray i e = UArray !i !i !ByteArray data ByteArray = ByteArray !Int !BytePtr type BytePtr = ForeignPtr Word8 Hugs implementation actually works via Storable class, and i duplicated this in my own ArrayRef lib (only for Hugs, of course) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Bulat Ziganshin wrote:
Hello Simon,
Monday, November 20, 2006, 3:44:16 PM, you wrote:
implemented as a sequence of bytes either; indeed the Hugs implementation doesn't represent a UArray using unboxed elements.
really? :)
data UArray i e = UArray !i !i !ByteArray
data ByteArray = ByteArray !Int !BytePtr
type BytePtr = ForeignPtr Word8
Hugs implementation actually works via Storable class, and i duplicated this in my own ArrayRef lib (only for Hugs, of course)
Ok, I misremembered - thanks for the clarification. Cheers, SImon
participants (5)
-
Bulat Ziganshin
-
Chris Kuklewicz
-
dons@cse.unsw.edu.au
-
Iavor Diatchki
-
Simon Marlow