Marshall Multidimensional list, multidimensional array

glynn at gclements.plus.com glynn at gclements.plus.com
Wed Nov 10 11:22:29 EST 2004


Peter Simons wrote:

>  > [[Int]] to int[][]
> 
> Pardon me if I'm telling you something you already know, but I
> wanted to make sure you are aware of it.
> 
> int[][] is a very different type than [[Int]] is. An int[][]
> is a pointer to an array of pointers to integers:

No it isn't; it's an array of arrays of integers. As C passes arrays
by reference rather than value, it will be passed as a pointer to
arrays of integers.

However, you can't use "int[][]" directly as a type; all dimensions
other than the first must be specified. E.g. "int [][4]" is an array
of arrays-of-length-4 of integers, and will be passed as a pointer to
arrays-of-length-4 of integers (i.e. incrementing the pointer will
increment by 4*sizeof(int) bytes).

Consequently, you can't directly use withArray, as that only works on
lists whose elements are members of the Storable class, and lists
aren't themselves members of Storable.

To marshall such a list, one approach would be to simply flatten the
list with concat, i.e.:

	withArray2D :: (Storable a) => [[a]] -> (Ptr a -> IO b) -> IO b
	withArray2D xs f = withArray (concat xs) f

So long as all of the sublists are of the same length, this will do
the right thing. If the sublists are of differing length, you would
first need to either truncate or pad them to the same length, e.g.:

	withArray2D :: (Storable a) => [[a]] -> (Ptr a -> IO b) -> IO b
	withArray2D xs f = withArray xs' f
		where	xs' = concat $ map (take dim) xs
			dim = minimum $ map length xs

Padding is slightly more complex, as you have to choose a value with
which to pad.

-- 
Glynn Clements <glynn at gclements.plus.com>


More information about the Glasgow-haskell-users mailing list