tags:

views:

142

answers:

3

Hello,

I see that I can map a function over mutable arrays with mapArray, but there doesn't seem to be something like mapM (and mapM_). mapArray won't let me print its elements, for example:

import Data.Array.Storable

arr <- newArray (1,10) 42 :: IO  -- answer to Life, Universe and Everything
x <- readLn :: IO Int
mapArray (putStrLn.show) arr -- <== this doesn't work!

The result will be:

No instances for (MArray StorableArray Int m,
                  MArray StorableArray (IO ()) m)
  arising from a use of `mapArray' at <interactive>:1:0-27
Possible fix:
  add an instance declaration for
  (MArray StorableArray Int m, MArray StorableArray (IO ()) m)
In the expression: mapArray (putStrLn . show) arr
In the definition of `it': it = mapArray (putStrLn . show) arr

Is there something like that in Haskell (or in GHC even if not standard Haskell)?

Also, I found no foldr/foldl functions for arrays (mutable or not). Do they exist?

Thanks a lot!

+2  A: 

For the example of printing all the elements: you can use "mapM_ print . elems".

But it sounds like you want to create a new array where each value is the result of a monadic action of the previous one? In that case:

arrayMapM :: (Monad m, Ix i) => (a -> m b) -> Array i a -> m (Array i b)
arrayMapM func src =
  liftM (listArray (bounds src)) . mapM func . elems $ src
yairchu
Thanks -- but that seems to work for Arrays, and not for StorableArrays. (I'd like to interface with C, passing the array pointer, so I'd rather use StorableArrays)
Jay
@Jay: do you want to change the array's values in-place? not creating a new one?
yairchu
@yairchu: yes. The array should be mutable and I need to pass it to C external functions. There is also a performance concern.
Jay
+3  A: 

Perhaps use one of the other array libraries, if you're doing a lot of mutation? Like uvector?

Otherwise,

forM_ [1..n] \$ \i ->. unsafeWrite x i

should be fine.

Don Stewart
Thanks a lot! forM_ [1..10::Int] $ (\i -> readArray arr i >>= putStrLn.show) works for putStrLn (and should work for other impure functions).uvector seems very nice. Would you recommend uvector or StorableArrays if I want to call C functions via FFI in speed-critical code?
Jay
"if I want to call C functions via FFI in speed-critical code?" --- then you have to use Foreign or Storable arrays, since they are pinned in memory.
Don Stewart
+4  A: 

Import the module Data.Traversable. It defines a typeclass for just what you want with instances already defined for array and all sorts of things. It has generalized versions of sequence and mapM, plus some even more general functions that you probably won't bother with very often.

Just a simple

import Data.Traversable as T

T.mapM doIOStuff arr

works fine.

Tirpen