HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Modulestreamly-core-0.2.2Haskell2010

Streamly.Internal.Data.MutByteArray

  • 11 types
  • 5 classes
  • 73 values

MutByteArray

21 declarations
valueunsafePinnedAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
#

Use a MutByteArray as Ptr a. This is useful when we want to pass an array as a pointer to some operating system call or to a "safe" FFI call.

If the array is not pinned it is copied to pinned memory before passing it to the monadic action.

Performance Notes: Forces a copy if the array is not pinned. It is advised that the programmer keeps this in mind and creates a pinned array opportunistically before this operation occurs, to avoid the cost of a copy if possible.

Unsafe because of direct pointer operations. The user must ensure that they are writing within the legal bounds of the array.

Pre-release

Unbox

19 declarations
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
datadata BoundedPtr
#

A location inside a mutable byte array with the bound of the array. Is it cheaper to just get the bound using the size of the array whenever needed?

newtypenewtype Peeker a
#

Chains peek functions that pass the current position to the next function

Constructors

Instances3Monad, Functor, Applicative
  • Monad PeekerDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Functor PeekerDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Applicative PeekerDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
classclass PeekRep (f :: Type -> Type) where
#

Methods

Instances6PeekRep
  • PeekRep U1Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • PeekRep V1Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox a => PeekRep (K1 i a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • (MaxArity256 (SumArity (f :+: g)), KnownNat (SumArity (f :+: g)), PeekRepSum 0 (f :+: g)) => PeekRep (f :+: g)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • (PeekRep f, PeekRep g) => PeekRep (f :*: g)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • PeekRep f => PeekRep (M1 i c f)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
classclass PokeRep (f :: Type -> Type) where
#

Methods

Instances6PokeRep
  • PokeRep U1Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • PokeRep V1Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox a => PokeRep (K1 i a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • (MaxArity256 (SumArity (f :+: g)), PokeRepSum 0 (f :+: g)) => PokeRep (f :+: g)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • (PokeRep f, PokeRep g) => PokeRep (f :*: g)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • PokeRep f => PokeRep (M1 i c f)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
classclass SizeOfRep (f :: Type -> Type) where
#

Implementation of sizeOf that works on the generic representation of an ADT.

Methods

Instances6SizeOfRep
  • SizeOfRep U1Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • SizeOfRep V1Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • Unbox a => SizeOfRep (K1 i a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • (MaxArity256 (SumArity (f :+: g)), SizeOfRepSum f, SizeOfRepSum g) => SizeOfRep (f :+: g)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • (SizeOfRep f, SizeOfRep g) => SizeOfRep (f :*: g)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
  • SizeOfRep f => SizeOfRep (M1 i c f)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox
valuederiveUnbox :: Q [Dec] -> Q [Dec]
#

Given an Unbox instance declaration splice without the methods (e.g. [d|instance Unbox a => Unbox (Maybe a)|]), generate an instance declaration including all the type class method implementations.

Usage:

$(deriveUnbox [d|instance Unbox a => Unbox (Maybe a)|])
datadata DataCon
#

Simplified info about a Con. Omits deriving, strictness, and kind info. This is much nicer than consuming Con directly, because it unifies all the constructors into one.

Constructors

Instances3Eq, Ord, Show
  • Eq DataConDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox.TH
  • Ord DataConDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox.TH
  • Show DataConDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unbox.TH

Serialize

1 declaration
classclass Serialize a where
#

The Serialize type class provides operations for serialization and deserialization of general Haskell data types to and from their byte stream representation.

Unlike Unbox, Serialize uses variable length encoding, therefore, it can serialize recursive and variable length data types like lists, or variable length sum types where the length of the value may vary depending on a particular constructor. For variable length data types the length is encoded along with the data.

The deserializeAt operation reads bytes from the mutable byte array and builds a Haskell data type from these bytes, the number of bytes it reads depends on the type and the encoded value it is reading. serializeAt operation converts a Haskell data type to its binary representation which must consist of as many bytes as added by the addSizeTo operation for that value and then stores these bytes into the mutable byte array. The programmer is expected to use the addSizeTo operation and allocate an array of sufficient length before calling serializeAt.

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 Template Haskell, or written manually.

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

Example1 expression
:{data Object = Object    { _obj1 :: [Int]    , _obj2 :: Int    }:}
import Streamly.Data.MutByteArray (deriveSerialize)
$(deriveSerialize [d|instance Serialize Object|])

See Streamly.Data.MutByteArray.deriveSerialize and Streamly.Data.MutByteArray.deriveSerializeWith for more information on deriving using Template Haskell.

Here is an example of a manual instance.

Example1 expression
import Streamly.Data.MutByteArray (Serialize(..))
Example1 expression
:{instance Serialize Object where    addSizeTo acc obj = addSizeTo (addSizeTo acc (_obj1 obj)) (_obj2 obj)    deserializeAt i arr len = do         -- Check the array bounds before reading        (i1, x0) <- deserializeAt i arr len        (i2, x1) <- deserializeAt i1 arr len        pure (i2, Object x0 x1)    serializeAt i arr (Object x0 x1) = do        i1 <- serializeAt i arr x0        i2 <- serializeAt i1 arr x1        pure i2:}

Methods

  • addSizeTo :: Int -> a -> Int

    addSizeTo accum value returns accum incremented by the size of the serialized representation of value in bytes. Size cannot be zero. It should be at least 1 byte.

  • deserializeAt :: Int -> MutByteArray -> Int -> IO (Int, a)

    deserializeAt byte-offset array arrayLen deserializes a value from the given byte-offset in the array. Returns a tuple consisting of the next byte-offset and the deserialized value.

    The arrayLen passed is the entire length of the input buffer. It is to be used to check if we would overflow the input buffer when deserializing.

    Throws an exception if the operation would exceed the supplied arrayLen.

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

    serializeAt byte-offset array value writes the serialized representation of the value in the array at the given byte-offset. Returns the next byte-offset.

    This is an unsafe operation, the programmer must ensure that the array has enough space available to serialize the value as determined by the addSizeTo operation.

Instances27Serialize, …
  • Serialize IntegerDefined in streamly-core-0.2.2 · Streamly.Internal.Data.MutByteArray · orphan
  • Serialize Int16Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize Int32Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize Int64Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize Int8Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize Word16Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize Word32Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize Word64Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize Word8Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize BoolDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize CharDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize DoubleDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize FloatDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize IntDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize WordDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize LiftedIntegerDefined in streamly-core-0.2.2 · Streamly.Internal.Data.MutByteArray
  • Serialize ()Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize (FunPtr a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize (Ptr a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize (StablePtr a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize (Array a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize a => Serialize (Maybe a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.MutByteArray · orphan
  • Serialize a => Serialize (CompactList a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.TH.RecHeader
  • Serialize a => Serialize [a]Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type
  • Serialize (Proxy a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.MutByteArray · orphan
  • (Serialize a, Serialize b) => Serialize (Either a b)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.MutByteArray · orphan
  • (Serialize a, Serialize b) => Serialize (a, b)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Serialize.Type

Serialize TH

48 declarations
datadata SerializeConfig
#

Configuration to control how the Serialize instance is generated. The configuration is opaque and is modified by composing config modifier functions, for example:

Example1 expression
(inlineSerializeAt (Just NoInline)) . (inlineSerializeAt (Just Inlinable))

The default configuration settings are:

The following experimental options are also available:

How should we inline the serialize function? The default 'Just Inline'. However, aggressive inlining can bloat the code and increase in compilation times when there are big functions and too many nesting levels so you can change it accordingly. A Nothing value leaves the decision to the compiler.

valuederiveSerialize :: Q [Dec] -> Q [Dec]
#

Given an Serialize instance declaration splice without the methods (e.g. [d|instance Serialize a => Serialize (Maybe a)|]), generate an instance declaration including all the type class method implementations.

Example1 expression
deriveSerialize = deriveSerializeWith id

Usage:

$(deriveSerialize
      [d|instance Serialize a => Serialize (Maybe a)|])

deriveSerializeWith config-modifier instance-dec generates a template Haskell splice consisting of a declaration of a Serialize instance. instance-dec is a template Haskell declaration splice consisting of a standard Haskell instance declaration without the type class methods (e.g. [d|instance Serialize a => Serialize (Maybe a)|]).

The type class methods for the given instance are generated according to the supplied config-modifier parameter. See SerializeConfig for default configuration settings.

Usage:

$(deriveSerializeWith
      ( inlineSerializeAt (Just NoInline)
      . inlineDeserializeAt (Just NoInline)
      )
      [d|instance Serialize a => Serialize (Maybe a)|])

Experimental

In sum types, use Latin-1 encoded original constructor names rather than binary values to identify constructors. This option is not applicable to product types.

This option enables the following behavior:

  • Reordering: Order of the fields can be changed without affecting serialization.

  • Addition: If a field is added in the new version, the old version of the data type can still be deserialized by the new version. The new value would never occur in the old one.

  • Deletion: If a field is deleted in the new version, deserialization of the old version will result in an error. TBD: We can possibly designate a catch-all case to handle this scenario.

Note that if you change a type, change the semantics of a type, or delete a field and add a new field with the same name, deserialization of old data may result in silent unexpected behavior.

This option has to be the same on both encoding and decoding side.

The default is False.

Experimental

In explicit record types, use Latin-1 encoded record field names rather than binary values to identify the record fields. Note that this option is not applicable to sum types. Also, it does not work on a product type which is not a record, because there are no field names to begin with.

This option enables the following behavior:

  • Reordering: Order of the fields can be changed without affecting serialization.

  • Addition: If a Maybe type field is added in the new version, the old version of the data type can still be deserialized by the new version, the field value in the older version is assumed to be Nothing. If any other type of field is added, deserialization of the older version results in an error but only when that field is actually accessed in the deserialized record.

  • Deletion: If a field is deleted in the new version and it is encountered in a previously serialized version then the field is discarded.

This option has to be the same on both encoding and decoding side.

There is a constant performance overhead proportional to the total length of the record field names and the number of record fields.

The default is False.

Orphan instances

4 instances