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

Modulestreamly-core-0.2.2Haskell2010

Streamly.Data.MutArray

This module provides a mutable version of Streamly.Data.Array. The contents of a mutable array can be modified in-place. For general documentation, please refer to the original module.

Please refer to Streamly.Internal.Data.MutArray for functions that have not yet been released.

For mutable arrays that work on boxed types, not requiring the Unbox constraint, please refer to Streamly.Data.MutArray.Generic.

  • 1 type
  • 1 class
  • 34 values

Setup

0 declarations

To execute the code examples provided in this module in ghci, please run the following commands first.

Example4 expressions
:mimport qualified Streamly.Data.Fold as Foldimport qualified Streamly.Data.MutArray as MutArrayimport qualified Streamly.Data.Stream as Stream

For APIs that have not been released yet.

Example1 expression
import Streamly.Internal.Data.MutArray as MutArray

Mutable Array Type

1 declaration
datadata MutArray a
#

An unboxed mutable array. An array is created with a given length and capacity. Length is the number of valid elements in the array. Capacity is the maximum number of elements that the array can be expanded to without having to reallocate the memory.

The elements in the array can be mutated in-place without changing the reference (constructor). However, the length of the array cannot be mutated in-place. A new array reference is generated when the length changes. When the length is increased (upto the maximum reserved capacity of the array), the array is not reallocated and the new reference uses the same underlying memory as the old one.

Several routines in this module allow the programmer to control the capacity of the array. The programmer can control the trade-off between memory usage and performance impact due to reallocations when growing or shrinking the array.

Construction

6 declarations
valueemptyOf :: (MonadIO m, Unbox a) => Int -> m (MutArray a)
#

Allocates an unpinned array of zero length but growable to the specified capacity without reallocation.

valuefromListN :: (MonadIO m, Unbox a) => Int -> [a] -> m (MutArray a)
#

Create a MutArray from the first N elements of a list. The array is allocated to size N, if the list terminates before N elements then the array may hold less than N elements.

valuecreateOf :: (MonadIO m, Unbox a) => Int -> Fold m a (MutArray a)
#

createOf n folds a maximum of n elements from the input stream to an MutArray.

Example3 expressions
createOf = MutArray.createOfWith MutArray.newcreateOf n = Fold.take n (MutArray.unsafeCreateOf n)createOf n = MutArray.appendN n (MutArray.emptyOf n)

Pinning & Unpinning

3 declarations
valuepin :: MutArray a -> IO (MutArray a)
#

Return a copy of the array in pinned memory if unpinned, else return the original array.

valueunpin :: MutArray a -> IO (MutArray a)
#

Return a copy of the array in unpinned memory if pinned, else return the original array.

Appending elements

1 declaration
valuesnoc :: (MonadIO m, Unbox a) => MutArray a -> a -> m (MutArray a)
#

The array is mutated to append an additional element to it. If there is no reserved space available in the array then it is reallocated to double the original size.

This is useful to reduce allocations when appending unknown number of elements.

Note that the returned array may be a mutated version of the original array.

Example1 expression
snoc = MutArray.snocWith (* 2)

Performs O(n * log n) copies to grow, but is liberal with memory allocation.

Appending streams

2 declarations
valueappendN
  1. :: (MonadIO m, Unbox a)
  2. => Int
  3. -> m (MutArray a)
  4. -> Fold m a (MutArray a)
#

Append n elements to an existing array. Any free space left in the array after appending n elements is lost.

Example1 expression
appendN n initial = Fold.take n (MutArray.unsafeAppendN n initial)
valueappend :: (MonadIO m, Unbox a) => m (MutArray a) -> Fold m a (MutArray a)
#

append action mutates the array generated by action to append the input stream. If there is no reserved space available in the array it is reallocated to double the size.

Note that the returned array may be a mutated version of original array.

Example1 expression
append = MutArray.appendWith (* 2)

Inplace mutation

5 declarations
valueputIndex :: (MonadIO m, Unbox a) => Int -> MutArray a -> a -> m ()
#

O(1) Write the given element at the given index in the array. Performs in-place mutation of the array.

Example3 expressions
putIndex ix arr val = MutArray.modifyIndex ix arr (const (val, ()))f = MutArray.putIndicesputIndex ix arr val = Stream.fold (f arr) (Stream.fromPure (ix, val))
valueputIndexUnsafe :: (MonadIO m, Unbox a) => Int -> MutArray a -> a -> m ()
#

Write the given element to the given index of the array. Does not check if the index is out of bounds of the array.

Pre-release

valuemodifyIndexUnsafe
  1. :: (MonadIO m, Unbox a)
  2. => Int
  3. -> MutArray a
  4. -> a -> (a, b)
  5. -> m b
#

Modify a given index of an array using a modifier function.

Unsafe because it does not check the bounds of the array.

Pre-release

valuemodify :: (MonadIO m, Unbox a) => MutArray a -> (a -> a) -> m ()
#

Modify each element of an array using the supplied modifier function.

This is an in-place equivalent of an immutable map operation.

Pre-release

Random access

2 declarations
valuegetIndexUnsafe :: (MonadIO m, Unbox a) => Int -> MutArray a -> m a
#

Return the element at the specified index without checking the bounds.

Unsafe because it does not check the bounds of the array.

Conversion

1 declaration

Streams

2 declarations

Unfolds

2 declarations

Casting

2 declarations
valuecast :: Unbox b => MutArray a -> Maybe (MutArray b)
#

Cast an array having elements of type a into an array having elements of type b. The length of the array should be a multiple of the size of the target element otherwise Nothing is returned.

Size

1 declaration
valuelength :: Unbox a => MutArray a -> Int
#

O(1) Get the length of the array i.e. the number of elements in the array.

Note that byteLength is less expensive than this operation, as length involves a costly division operation.

Re-exports

1 declaration
classclass Unbox a where
#

The Unbox type class provides operations for serialization (unboxing) and deserialization (boxing) of fixed-length, non-recursive Haskell data types to and from their byte stream representation.

Unbox uses fixed size encoding, therefore, size is independent of the value, it must be determined solely by the type. This restriction makes types with Unbox instances suitable for storing in arrays. Note that sum types may have multiple constructors of different sizes, the size of a sum type is computed as the maximum required by any constructor.

The peekAt operation reads as many bytes from the mutable byte array as the size of the data type and builds a Haskell data type from these bytes. pokeAt operation converts a Haskell data type to its binary representation which consists of size bytes and then stores these bytes into the mutable byte array. These operations do not check the bounds of the array, the user of the type class is expected to check the bounds before peeking or poking.

IMPORTANT: The serialized data's byte ordering remains the same as the host machine's byte order. Therefore, it can not be deserialized from host machines with a different byte ordering.

Instances can be derived via Generics, Template Haskell, or written manually. Note that the data type must be non-recursive. WARNING! Generic and Template Haskell deriving, both hang for recursive data types. Deriving via Generics is more convenient but Template Haskell should be preferred over Generics for the following reasons:

  1. Instances derived via Template Haskell provide better and more reliable performance.

  2. Generic deriving allows only 256 fields or constructor tags whereas template Haskell has no limit.

Here is an example, for deriving an instance of this type class using generics:

Example2 expressions
import GHC.Generics (Generic):{data Object = Object    { _int0 :: Int    , _int1 :: Int    } deriving Generic:}
Example2 expressions
import Streamly.Data.MutByteArray (Unbox(..))instance Unbox Object

To derive the instance via Template Haskell:

import Streamly.Data.MutByteArray (deriveUnbox)
$(deriveUnbox [d|instance Unbox Object|])

See Streamly.Data.MutByteArray.deriveUnbox for more information on deriving using Template Haskell.

If you want to write the instance manually:

Example1 expression
:{instance Unbox Object where    sizeOf _ = 16    peekAt i arr = do       -- Check the array bounds        x0 <- peekAt i arr        x1 <- peekAt (i + 8) arr        return $ Object x0 x1    pokeAt i arr (Object x0 x1) = do       -- Check the array bounds        pokeAt i arr x0        pokeAt (i + 8) arr x1:}

Methods

  • sizeOf :: Proxy a -> Int

    Get the size. Size cannot be zero, should be at least 1 byte.

  • peekAt :: Int -> MutByteArray -> IO a

    peekAt byte-offset array reads an element of type a from the the given the byte offset in the array.

    IMPORTANT: The implementation of this interface may not check the bounds of the array, the caller must not assume that.

  • peekByteIndex :: Int -> MutByteArray -> IO a
  • pokeAt :: Int -> MutByteArray -> a -> IO ()

    pokeAt byte-offset array writes an element of type a to the the given the byte offset in the array.

    IMPORTANT: The implementation of this interface may not check the bounds of the array, the caller must not assume that.

  • pokeByteIndex :: Int -> MutByteArray -> a -> IO ()
Instances30Unbox, …
  • Unbox FingerprintDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox IntPtrDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox WordPtrDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox Int16Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox Int32Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox Int64Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox Int8Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox IoSubSystemDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox Word16Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox Word32Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox Word64Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox Word8Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox BoolDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox CharDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox DoubleDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox FloatDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox IntDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox WordDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox MicroSecond64Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Time.Units
  • Unbox MilliSecond64Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Time.Units
  • Unbox NanoSecond64Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Time.Units
  • Unbox ()Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox (FunPtr a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox (Ptr a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox (StablePtr a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox a => Unbox (Complex a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox a => Unbox (Identity a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox a => Unbox (Down a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox a => Unbox (Ratio a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox a => Unbox (Const a b)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox

Deprecated

7 declarations