HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Moduleprimitive-0.9.1.0Haskell2010

Data.Primitive.SmallArray

Small arrays are boxed (im)mutable arrays.

The underlying structure of the Array type contains a card table, allowing segments of the array to be marked as having been mutated. This allows the garbage collector to only re-traverse segments of the array that have been marked during certain phases, rather than having to traverse the entire array.

SmallArray lacks this table. This means that it takes up less memory and has slightly faster writes. It is also more efficient during garbage collection so long as the card table would have a single entry covering the entire array. These advantages make them suitable for use as arrays that are known to be small.

The card size is 128, so for uses much larger than that, Array would likely be superior.

  • 2 types
  • 26 values
  • Packageprimitive-0.9.1.0
  • Exports28
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceSmallArray.hs
datadata SmallArray a
#

Constructors

Instances26Monad, Functor, MonadFix, MonadFail, Applicative, Foldable, …
valueindexSmallArray
  1. :: SmallArray a

    array

  2. -> Int

    index

  3. -> a
#

Look up an element in an immutable array.

Note: this function does not do bounds checking.

valueindexSmallArrayM
  1. :: Applicative m
  2. => SmallArray a

    array

  3. -> Int

    index

  4. -> m a
#

Look up an element in an immutable array.

The purpose of returning a result using an applicative is to allow the caller to avoid retaining references to the array. Evaluating the return value will cause the array lookup to be performed, even though it may not require the element of the array to be evaluated (which could throw an exception). For instance:

data Box a = Box a
...

f sa = case indexSmallArrayM sa 0 of
  Box x -> ...

x is not a closure that references sa as it would be if we instead wrote:

let x = indexSmallArray sa 0

It also does not prevent sa from being garbage collected.

Note that Identity is not adequate for this use, as it is a newtype, and cannot be evaluated without evaluating the element.

Note: this function does not do bounds checking.

valueindexSmallArray## :: SmallArray a -> Int -> (# a #)
#

Read a value from the immutable array at the given index, returning the result in an unboxed unary tuple. This is currently used to implement folds.

Note: this function does not do bounds checking.

valuecloneSmallArray
  1. :: SmallArray a

    source

  2. -> Int

    offset

  3. -> Int

    length

  4. -> SmallArray a
#

Create a copy of a slice of an immutable array.

Note: The provided array should contain the full subrange specified by the two Ints, but this is not checked.

valuefreezeSmallArray
  1. :: PrimMonad m
  2. => SmallMutableArray (PrimState m) a

    source

  3. -> Int

    offset

  4. -> Int

    length

  5. -> m (SmallArray a)
#

Create an immutable array corresponding to a slice of a mutable array.

This operation copies the portion of the array to be frozen.

Note: The provided array should contain the full subrange specified by the two Ints, but this is not checked.

valuethawSmallArray
  1. :: PrimMonad m
  2. => SmallArray a

    source

  3. -> Int

    offset

  4. -> Int

    length

  5. -> m (SmallMutableArray (PrimState m) a)
#

Create a mutable array corresponding to a slice of an immutable array.

This operation copies the portion of the array to be thawed.

Note: The provided array should contain the full subrange specified by the two Ints, but this is not checked.

valuecreateSmallArray
  1. :: Int
  2. -> a
  3. -> forall s. SmallMutableArray s a -> ST s ()
  4. -> SmallArray a
#

Create an array of the given size with a default value, apply the monadic function and freeze the result. If the size is 0, return emptySmallArray (rather than a new copy thereof).

createSmallArray 0 _ _ = emptySmallArray
createSmallArray n x f = runSmallArray $ do
  mary <- newSmallArray n x
  f mary
  pure mary

Get the number of elements in a mutable array. Unlike sizeofSmallMutableArray, this function will be sure to produce the correct result if SmallMutableArray has been shrunk in place. Consider the following:

do
  sa <- newSmallArray 10 x
  print $ sizeofSmallMutableArray sa
  shrinkSmallMutableArray sa 5
  print $ sizeofSmallMutableArray sa

The compiler is well within its rights to eliminate the second size check and print 10 twice. However, getSizeofSmallMutableArray will check the size each time it's executed (not evaluated), so it won't have this problem:

do
  sa <- newSmallArray 10 x
  print =<< getSizeofSmallMutableArray sa
  shrinkSmallMutableArray sa 5
  print =<< getSizeofSmallMutableArray sa

will certainly print 10 and then 5.

valueresizeSmallMutableArray
  1. :: PrimMonad m
  2. => SmallMutableArray (PrimState m) a
  3. -> Int

    New size

  4. -> a

    Newly created slots initialized to this element. Only used when array is grown.

  5. -> m (SmallMutableArray (PrimState m) a)
#

Resize a mutable array to new specified size. The returned SmallMutableArray is either the original SmallMutableArray resized in-place or, if not possible, a newly allocated SmallMutableArray with the original content copied over.

To avoid undefined behaviour, the original SmallMutableArray shall not be accessed anymore after a resizeSmallMutableArray has been performed. Moreover, no reference to the old one should be kept in order to allow garbage collection of the original SmallMutableArray in case a new SmallMutableArray had to be allocated.

valuetraverseSmallArrayP
  1. :: PrimMonad m
  2. => a -> m b
  3. -> SmallArray a
  4. -> m (SmallArray b)
#

This is the fastest, most straightforward way to traverse an array, but it only works correctly with a sufficiently "affine" PrimMonad instance. In particular, it must only produce one result array. Control.Monad.Trans.List.ListT-transformed monads, for example, will not work right at all.