4.21. MArray

The MArray module provides a class of mutable arrays, parameterised over the array type, element type and the monad in which the array can be used:

  class (Monad m, HasBounds a) => MArray a e m where
     newArray   :: Ix ix => (ix,ix) -> e -> m (a ix e)
     newArray_  :: Ix ix => (ix,ix) -> m (a ix e)
     readArray  :: Ix ix => a ix e -> ix -> m e
     writeArray :: Ix ix => a ix e -> ix -> e -> m ()

There are two functions for building arrays: newArray and newArray_. The former takes an initial value and sets every element of the new array to this value, whereas the latter leaves all of the elements of the new array undefined.

The readArray and writeArray operations allow for reading and writing to/from the array.

The IOArray (Section 4.19.3) and STArray (Section 4.31) types are both instances of MArray:

data STArray s ix e
instance HasBounds (STArray s)
instance MArray (STArray s) e (ST s)

data IOArray ix e
instance HasBounds IOArray
instance MArray IOArray e IO

There are also strict unboxed versions of IOArray and STArray, namely IOUArray STUArray and instances of MArray for these types with common integral element types:

data STUArray s ix e
instance HasBounds (STUArray s)
instance MArray (STArray s) Bool          (ST s)
instance MArray (STArray s) Char          (ST s)
instance MArray (STArray s) Int           (ST s)
instance MArray (STArray s) Word          (ST s)
instance MArray (STArray s) Addr          (ST s)
instance MArray (STArray s) (Ptr a)       (ST s)
instance MArray (STArray s) Float         (ST s)
instance MArray (STArray s) Double        (ST s)
instance MArray (STArray s) (StablePtr a) (ST s)
instance MArray (STArray s) Int8          (ST s)
instance MArray (STArray s) Int16         (ST s)
instance MArray (STArray s) Int32         (ST s)
instance MArray (STArray s) Int64         (ST s)
instance MArray (STArray s) Word8         (ST s)
instance MArray (STArray s) Word16        (ST s)
instance MArray (STArray s) Word32        (ST s)
instance MArray (STArray s) Word64        (ST s)

data IOUArray ix e
instance HasBounds IOUArray
instance MArray IOArray Bool          IO
instance MArray IOArray Char          IO
instance MArray IOArray Int           IO
instance MArray IOArray Word          IO
instance MArray IOArray Addr          IO
instance MArray IOArray (Ptr a)       IO
instance MArray IOArray Float         IO
instance MArray IOArray Double        IO
instance MArray IOArray (StablePtr a) IO
instance MArray IOArray Int8          IO
instance MArray IOArray Int16         IO
instance MArray IOArray Int32         IO
instance MArray IOArray Int64         IO
instance MArray IOArray Word8         IO
instance MArray IOArray Word16        IO
instance MArray IOArray Word32        IO
instance MArray IOArray Word64        IO

4.21.1. Freezing and thawing arrays

An MArray can be converted into an IArray (Section 4.17), by freezing it:

  freeze :: (Ix ix, MArray a e m, IArray b e) => a ix e -> m (b ix e)

The IArray returned is independent of the original MArray, so further modifications to the mutable version won't affect the frozen one. The usual implementation of freeze is to make a copy of the array.

In many cases, the additional copy is unnecessary, for example when freezing is the last operation on the mutable version of the array. For these cases, an unsafe version of freeze is provided which may not copy[1] the array:

  unsafeFreeze :: (Ix ix, MArray a e m, IArray b e) => a ix e -> m (b ix e)

The dual to freeze is thaw, which converts an IArray into an MArray:

  thaw :: (Ix ix, IArray a e, MArray b e m) => a ix e -> m (b ix e)

As with freeze, thaw needs to make a copy of the array. For the cases when you know the copy is unnecessary, we also provide unsafeThaw:

  unsafeThaw :: (Ix ix, IArray a e, MArray b e m) => a ix e -> m (b ix e)

4.21.2. Useful combinators

MArray also provides versions of the following standard array combinators. Note that they have slightly different types from the versions in Array and IArray, mostly to accomodate the requirement that an MArray must be used within a monad:

getAssocs    :: (Ix ix, MArray a e m) => a ix e -> m [(ix,e)]

indices      :: (Ix ix, HasBounds a) => a ix e -> [ix]

mapArray     :: (Ix ix, MArray a x m, MArray a y m) => 
                    (x->y) -> a ix x -> m (a ix y)

newListArray :: (Ix ix, MArray a e m) => (ix,ix) -> [e] -> m (a ix e)
          
getElems     :: (Ix ix, MArray a e m) => a ix e -> m [e]
          
mapIndixes   :: (Ix ix, Ix iy, MArray a e m) => 
                    (ix,ix) -> (ix->iy) -> a iy e -> m (a ix e)

Notes

[1]

The default implementation of unsafeFreeze is freeze, but it is expected that specialised versions which omit the copy are provided for the common array types.