HORIZON HASKELLDocslts/ghc-10.0.x8c2f8e82026-10-19Search names, modules, packages, or :: a typeCtrl K

GHC 10.0.0.20260917 · lts/ghc-10.0.x · 8c2f8e8 · 2026-10-19

Modulemassiv-1.0.5.0Haskell2010

Data.Massiv.Array.Mutable

  • 1 type
  • 1 class
  • 71 values
  • Packagemassiv-1.0.5.0
  • Exports78
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceCommon.hs

Size

6 declarations
valueouterSlicesMArray
  1. :: (Index (Lower ix), Index ix, Manifest r e)
  2. => Comp
  3. -> MArray s r ix e
  4. -> Vector D (MArray s r (Lower ix) e)
#

O(1) - Take all outer slices of a mutable array and construct a delayed vector out of them. In other words it applies outerSliceMArrayM to each outer index. Same as outerSlices function, but for mutable arrays.

Examples
Example3 expressions
import Data.Massiv.Array as Aarr <- resizeM (Sz2 4 7) $ makeArrayR P Seq (Sz1 28) (+10)arrArray P Seq (Sz (4 :. 7))  [ [ 10, 11, 12, 13, 14, 15, 16 ]  , [ 17, 18, 19, 20, 21, 22, 23 ]  , [ 24, 25, 26, 27, 28, 29, 30 ]  , [ 31, 32, 33, 34, 35, 36, 37 ]  ]

Here we can see we can get individual rows from a mutable matrix

Example3 expressions
marr <- thawS arrimport Control.Monad ((<=<))mapIO_ (print <=< freezeS)  $ outerSlicesMArray Seq marrArray P Seq (Sz1 7)  [ 10, 11, 12, 13, 14, 15, 16 ]Array P Seq (Sz1 7)  [ 17, 18, 19, 20, 21, 22, 23 ]Array P Seq (Sz1 7)  [ 24, 25, 26, 27, 28, 29, 30 ]Array P Seq (Sz1 7)  [ 31, 32, 33, 34, 35, 36, 37 ]

For the sake of example what if our goal was to mutate array in such a way that rows from the top half were swapped with the bottom half:

Example5 expressions
(top, bottom) <- splitAtM 1 2 $ outerSlicesMArray Seq marrmapIO_ (print <=< freezeS) topArray P Seq (Sz1 7)  [ 10, 11, 12, 13, 14, 15, 16 ]Array P Seq (Sz1 7)  [ 17, 18, 19, 20, 21, 22, 23 ]mapIO_ (print <=< freezeS) bottomArray P Seq (Sz1 7)  [ 24, 25, 26, 27, 28, 29, 30 ]Array P Seq (Sz1 7)  [ 31, 32, 33, 34, 35, 36, 37 ]szipWithM_ (zipSwapM_ 0) top bottomfreezeS marrArray P Seq (Sz (4 :. 7))  [ [ 24, 25, 26, 27, 28, 29, 30 ]  , [ 31, 32, 33, 34, 35, 36, 37 ]  , [ 10, 11, 12, 13, 14, 15, 16 ]  , [ 17, 18, 19, 20, 21, 22, 23 ]  ]

Element-wise mutation

14 declarations
valuewrite_
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => MArray (PrimState m) r ix e
  3. -> ix
  4. -> e
  5. -> m ()
#

O(1) - Write an element into the cell of a mutable array. Same as write function in case of an out of bounds index it is noop, but unlike write, there is no information is returned about was the writing of element successful or not. In other words, just like writeM, but doesn't throw an exception.

valuemodify
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => MArray (PrimState m) r ix e

    Array to mutate.

  3. -> (e -> m e)

    Monadic action that modifies the element

  4. -> ix

    Index at which to perform modification.

  5. -> m (Maybe e)
#

O(1) - Modify an element in the cell of a mutable array with a supplied action. Returns the previous value, if index was not out of bounds.

valuemodify_
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => MArray (PrimState m) r ix e

    Array to mutate.

  3. -> (e -> m e)

    Monadic action that modifies the element

  4. -> ix

    Index at which to perform modification.

  5. -> m ()
#

O(1) - Same as modify, except that neither the previous value, nor any information on whether the modification was successful are returned. In other words, just like modifyM_, but doesn't throw an exception.

valuemodifyM
  1. :: (Manifest r e, Index ix, PrimMonad m, MonadThrow m)
  2. => MArray (PrimState m) r ix e

    Array to mutate.

  3. -> (e -> m e)

    Monadic action that modifies the element

  4. -> ix

    Index at which to perform modification.

  5. -> m e
#

O(1) - Modify an element in the cell of a mutable array with a supplied action. Throws an IndexOutOfBoundsException exception for invalid index and returns the previous value otherwise.

valuemodifyM_
  1. :: (Manifest r e, Index ix, PrimMonad m, MonadThrow m)
  2. => MArray (PrimState m) r ix e

    Array to mutate.

  3. -> (e -> m e)

    Monadic action that modifies the element

  4. -> ix

    Index at which to perform modification.

  5. -> m ()
#

O(1) - Same as modifyM, but discard the returned element

Examples
Example4 expressions
:set -XTypeApplicationsimport Control.Monad.STimport Data.Massiv.ArrayrunST $ newMArray' @P @Ix1 @Int (Sz1 3) >>= (\ma -> modifyM_ ma (pure . (+10)) 1 >> freezeS ma)Array P Seq (Sz1 3)  [ 0, 10, 0 ]
valueswapM
  1. :: (Manifest r e, Index ix, PrimMonad m, MonadThrow m)
  2. => MArray (PrimState m) r ix e
  3. -> ix

    Index for the first element, which will be returned as the first element in the tuple.

  4. -> ix

    Index for the second element, which will be returned as the second element in the tuple.

  5. -> m (e, e)
#

O(1) - Swap two elements in a mutable array under the supplied indices. Throws an IndexOutOfBoundsException when either one of the indices is out of bounds and elements under those indices otherwise.

Operations on MArray

0 declarations

Immutable conversion

valuethaw
  1. :: (Manifest r e, Index ix, MonadIO m)
  2. => Array r ix e
  3. -> m (MArray RealWorld r ix e)
#

O(n) - Make a mutable copy of a pure array. Keep in mind that both freeze and thaw trigger a copy of the full array.

Example
Example6 expressions
import Data.Massiv.Array:set -XTypeApplicationsarr <- fromListsM @U @Ix2 @Double Par [[12,21],[13,31]]marr <- thaw arrmodify marr (pure . (+ 10)) (1 :. 0)Just 13.0freeze Par marrArray U Par (Sz (2 :. 2))  [ [ 12.0, 21.0 ]  , [ 23.0, 31.0 ]  ]
valuethawS
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => Array r ix e
  3. -> m (MArray (PrimState m) r ix e)
#

Same as thaw, but restrict computation to sequential only.

Example
Example6 expressions
import Data.Massiv.Array:set -XOverloadedListsthawS @P @Ix1 @Double [1..10]marr <- thawS @P @Ix1 @Double [1..10]writeM marr 5 100freezeS marrArray P Seq (Sz1 10)  [ 1.0, 2.0, 3.0, 4.0, 5.0, 100.0, 7.0, 8.0, 9.0, 10.0 ]
valuefreeze
  1. :: (Manifest r e, Index ix, MonadIO m)
  2. => Comp
  3. -> MArray RealWorld r ix e
  4. -> m (Array r ix e)
#

O(n) - Yield an immutable copy of the mutable array. Note that mutable representations have to be the same.

Example
Example4 expressions
import Data.Massiv.Arraymarr <- newMArray @P (Sz2 2 6) (0 :: Int)forM_ (range Seq 0 (Ix2 1 4)) $ \ix -> write marr ix 9freeze Seq marrArray P Seq (Sz (2 :. 6))  [ [ 9, 9, 9, 9, 0, 0 ]  , [ 0, 0, 0, 0, 0, 0 ]  ]

Create mutable

valuenewMArray'
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => Sz ix
  3. -> m (MArray (PrimState m) r ix e)
#

O(n) - Initialize a new mutable array. All elements will be set to some default value. For boxed arrays it will be a thunk with Uninitialized exception, while for others it will be simply zeros.

Examples
Example3 expressions
import Data.Massiv.Arraymarr <- newMArray' (Sz2 2 6) :: IO (MArray RealWorld P Ix2 Int)freeze Seq marrArray P Seq (Sz (2 :. 6))  [ [ 0, 0, 0, 0, 0, 0 ]  , [ 0, 0, 0, 0, 0, 0 ]  ]

Or using TypeApplications:

Example3 expressions
:set -XTypeApplicationsnewMArray' @P @Ix2 @Int (Sz2 2 6) >>= freezeSArray P Seq (Sz (2 :. 6))  [ [ 0, 0, 0, 0, 0, 0 ]  , [ 0, 0, 0, 0, 0, 0 ]  ]newMArray' @B @_ @Int (Sz2 2 6) >>= freezeS*** Exception: Uninitialized

Create pure

valuecreateArray_
  1. :: (Manifest r e, Index ix, MonadUnliftIO m)
  2. => Comp

    Computation strategy to use after MArray gets frozen and onward.

  3. -> Sz ix

    Size of the newly created array

  4. -> (Scheduler RealWorld () -> MArray RealWorld r ix e -> m a)

    An action that should fill all elements of the brand new mutable array

  5. -> m (Array r ix e)
#

Create a new array by supplying an action that will fill the new blank mutable array. Use createArray if you'd like to keep the result of the filling function.

Examples
Example3 expressions
:set -XTypeApplicationsimport Data.Massiv.ArraycreateArray_ @P @_ @Int Seq (Sz1 2) (\ s marr -> scheduleWork s (writeM marr 0 10) >> scheduleWork s (writeM marr 1 11))Array P Seq (Sz1 2)  [ 10, 11 ]
valuecreateArrayS_
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => Sz ix

    Size of the newly created array

  3. -> (MArray (PrimState m) r ix e -> m a)

    An action that should fill all elements of the brand new mutable array

  4. -> m (Array r ix e)
#

Create a new array by supplying an action that will fill the new blank mutable array. Use createArrayS if you'd like to keep the result of the filling function.

Examples
Example3 expressions
:set -XTypeApplicationsimport Data.Massiv.ArraycreateArrayS_ @P @_ @Int (Sz1 2) (\ marr -> write marr 0 10 >> write marr 1 12)Array P Seq (Sz1 2)  [ 10, 12 ]

Generate

valuegenerateArrayS
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => Sz ix

    Size of the array

  3. -> (ix -> m e)

    Element producing action

  4. -> m (Array r ix e)
#

Sequentially generate a pure array. Much like makeArray creates a pure array this function will use Manifest interface to generate a pure Array in the end, except that computation strategy is set to Seq. Element producing function no longer has to be pure but is a stateful action, becuase it is restricted to PrimMonad thus allows for sharing the state between computation of each element.

Examples
Example5 expressions
import Data.Massiv.Arrayimport Data.IORefref <- newIORef (0 :: Int)generateArrayS (Sz1 6) (\ i -> modifyIORef' ref (+i) >> print i >> pure i) :: IO (Array U Ix1 Int)012345Array U Seq (Sz1 6)  [ 0, 1, 2, 3, 4, 5 ]readIORef ref15
valuegenerateSplitSeedArray
  1. :: (Iterator it, Manifest r e, Index ix)
  2. => it

    Iterator

  3. -> g

    Initial seed

  4. -> (forall s. g -> ST s (g, g))

    An ST action that can split a seed into two independent seeds. It will be called the same number of times as the number of jobs that will get scheduled during parallelization. Eg. only once for the sequential case.

  5. -> Comp

    Computation strategy.

  6. -> Sz ix

    Resulting size of the array.

  7. -> (forall s. Ix1 -> ix -> g -> ST s (e, g))

    An ST action that produces a value and the next seed. It takes both versions of the index, in linear and in multi-dimensional forms, as well as the current seeding value. Returns the element for the array cell together with the new seed that will be used for the next element generation

  8. -> (g, [g], Array r ix e)

    Returned values are:

    • The final split of the supplied seed.

    • Results of scheduled jobs in the same order that they where scheduled

    • Final array that was fully filled using the supplied action and iterator.

#

Similar to makeSplitSeedArray, except it will produce a Manifest array and will return back the last unused seed together with all final seeds produced by each scheduled job. This function can be thought of as an unfolding done in parallel while iterating in a customizable manner.

Stateful worker threads

Unfold

valueunfoldrPrimM_
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => Sz ix

    Size of the desired array

  3. -> (a -> m (e, a))

    Unfolding action

  4. -> a

    Initial accumulator

  5. -> m (Array r ix e)
#

Sequentially unfold an array from the left.

Examples

Create an array with Fibonacci numbers while performing an IO action at each iteration.

Example2 expressions
import Data.Massiv.ArrayunfoldrPrimM_ (Sz1 10) (\(f0, f1) -> (f0, (f1, f0 + f1)) <$ print f1) (0, 1) :: IO (Array P Ix1 Int)11235813213455Array P Seq (Sz1 10)  [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]
valueunfoldlPrimM_
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => Sz ix

    Size of the desired array

  3. -> (a -> m (a, e))

    Unfolding action

  4. -> a

    Initial accumulator

  5. -> m (Array r ix e)
#

Sequentially unfold an array from the left.

Examples

Create an array with Fibonacci numbers starting at the end while performing and IO action on the accumulator for each element of the array.

Example2 expressions
import Data.Massiv.ArrayunfoldlPrimM_ (Sz1 10) (\a@(f0, f1) -> let fn = f0 + f1 in print a >> return ((f1, fn), f0)) (0, 1) :: IO (Array P Ix1 Int)(0,1)(1,1)(1,2)(2,3)(3,5)(5,8)(8,13)(13,21)(21,34)(34,55)Array P Seq (Sz1 10)  [ 34, 21, 13, 8, 5, 3, 2, 1, 1, 0 ]

Mapping

valueforPrimM_
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => MArray (PrimState m) r ix e
  3. -> e -> m ()
  4. -> m ()
#

Sequentially loop over a mutable array while reading each element and applying an action to it. There is no mutation to the array, unless the action itself modifies it.

valueiforPrimM_
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => MArray (PrimState m) r ix e
  3. -> ix -> e -> m ()
  4. -> m ()
#

Sequentially loop over a mutable array while reading each element and applying an index aware action to it. There is no mutation to the array, unless the action itself modifies it.

valueiforLinearPrimM_
  1. :: (Manifest r e, Index ix, PrimMonad m)
  2. => MArray (PrimState m) r ix e
  3. -> Int -> e -> m ()
  4. -> m ()
#

Sequentially loop over a mutable array while reading each element and applying a linear index aware action to it. There is no mutation to the array, unless the action itself modifies it.

valuefor2PrimM_
  1. :: (PrimMonad m, Index ix, Manifest r1 e1, Manifest r2 e2)
  2. => MArray (PrimState m) r1 ix e1
  3. -> MArray (PrimState m) r2 ix e2
  4. -> e1 -> e2 -> m ()
  5. -> m ()
#

Sequentially loop over the intersection of two mutable arrays while reading elements from both and applying an action to it. There is no mutation to the actual arrays, unless the action itself modifies either one of them.

Modify

valuewithMArray_
  1. :: (Manifest r e, Index ix, MonadUnliftIO m)
  2. => Array r ix e
  3. -> Scheduler RealWorld () -> MArray RealWorld r ix e -> m a
  4. -> m (Array r ix e)
#

Create a copy of a pure array, mutate it in place and return its frozen version. The big difference between withMArrayS is that it's not only gonna respect the computation strategy supplied to it while making a copy, but it will also pass extra argumens to the action that suppose to modify the mutable copy of the source array. These two extra arguments are:

  • Number of capabilities derived from the Computation strategy of the array.

  • An action that can be used to schedule arbitrary number of jobs that will be executed in parallel.

  • And, of course, the mutable array itself.

Initialize

Computation

6 declarations
classclass Source r e => Manifest r e where
#

Manifest arrays are backed by actual memory and values are looked up versus computed as it is with delayed arrays. Because manifest arrays are located in memory their contents can be mutated once thawed into MArray. The process of changed a mutable MArray back into an immutable Array is called freezing.

Instances6Manifest
  • NFData e => Manifest BN eDefined in massiv-1.0.5.0 · Data.Massiv.Array.Manifest.Boxed
  • Storable e => Manifest S eDefined in massiv-1.0.5.0 · Data.Massiv.Array.Manifest.Storable
  • Manifest B eDefined in massiv-1.0.5.0 · Data.Massiv.Array.Manifest.Boxed
  • Manifest BL eDefined in massiv-1.0.5.0 · Data.Massiv.Array.Manifest.Boxed
  • Prim e => Manifest P eDefined in massiv-1.0.5.0 · Data.Massiv.Array.Manifest.Primitive
  • Unbox e => Manifest U eDefined in massiv-1.0.5.0 · Data.Massiv.Array.Manifest.Unboxed
data familydata family MArray s r ix e
#

Mutable version of a Manifest Array. The extra type argument s is for the state token used by IO and ST.

Instances9NFData, MArray, …
datadata RealWorld
#

RealWorld is deeply magical. It is primitive, but it is not unlifted (hence ptrArg). We never manipulate values of type RealWorld; it's only used in the type system, to parameterise State#.

Instances1Storable