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.
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.
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.
createOf n folds a maximum of n elements from the input stream to an
MutArray.
The array capacity is guranteed to be at least n.
Example3 expressions
>>> createOf = MutArray.createWithOf MutArray.emptyOf>>> createOf n = Fold.take n (MutArray.unsafeCreateOf n)>>> createOf n = MutArray.appendMax n MutArray.empty
Same as 'createMinOf using an initial array size of arrayChunkBytes bytes
rounded up to the element size. If the array is expected to be smaller than
arrayChunkBytes then use createMinOf to avoid wasting memory.
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 and aligned to a power of 2.
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.
Performs only O(n * log n) copies to grow, but is liberal with memory
allocation compared to snocGrowBy.
Fold append2 arr mutates the array arr to append the input stream. If
there is no reserved space available in the array it is reallocated to
double the size and aligned to power of 2.
Note that the returned array may be a mutated version of original array.
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.putIndices>>> putIndex ix arr val = Stream.fold (f arr) (Stream.fromPure (ix, val))
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.
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:
Instances derived via Template Haskell provide better and more reliable
performance.
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:}
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 and aligned to power of 2.
Note that the returned array may be a mutated version of original array.