Safe Haskell | None |
---|---|

Language | Haskell2010 |

`Storable`

records offer an efficient flat, packed representation
in memory. In particular, field access is constant time (i.e. it
doesn't depend on where in the record the field is) and as fast as
possible, but updating fields may not be as efficient. The
requirement is that all fields of a record have `Storable`

instances.

The implementation leaks into the usual vinyl lens API: the
requirement of `Storable`

instances necessitates specialization on
the functor argument of the record so that GHC can find all
required instances at compile time (this is required for
constant-time field access). What we do is allow ourselves to write
instances of the `RecElem`

and `RecSubset`

classes (that provide
the main vinyl lens API) that are restricted to particular choices
of the record functor. This is why the `SRec2`

type that implements
records here takes two functor arguments: they will usually be the
same; we fix one when writing instances and write instance contexts
that reference that type, and then require that the methods
(e.g. `rget`

) are called on records whose functor argument is equal
to the one we picked. For usability, we provide an `SRec`

type
whose lens API is fixed to `ElField`

as the functor. Other
specializations are possible, and the work of those instances can
always be passed along to the `SRec2`

functions.

Note that the lens field accessors for `SRec`

do not support
changing the types of the fields as they do for `Rec`

and
`ARec`

.

## Synopsis

- newtype SRec f ts = SRecNT {}
- toSRec :: Storable (Rec f ts) => Rec f ts -> SRec f ts
- fromSRec :: Storable (Rec f ts) => SRec f ts -> Rec f ts
- sget :: forall f t ts. FieldOffset f ts t => SRec2 f f ts -> f t
- sput :: forall (f :: u -> *) (t :: u) (ts :: [u]). (FieldOffset f ts t, Storable (Rec f ts), AllConstrained (FieldOffset f ts) ts) => f t -> SRec2 f f ts -> SRec2 f f ts
- slens :: (Functor g, FieldOffset f ts t, Storable (Rec f ts), AllConstrained (FieldOffset f ts) ts) => (f t -> g (f t)) -> SRec2 f f ts -> g (SRec2 f f ts)
- srecGetSubset :: forall (ss :: [u]) (rs :: [u]) (f :: u -> *). (RPureConstrained (FieldOffset f ss) rs, RPureConstrained (FieldOffset f rs) rs, RFoldMap rs, RMap rs, RApply rs, Storable (Rec f rs)) => SRec2 f f ss -> SRec2 f f rs
- srecSetSubset :: forall (f :: u -> *) (ss :: [u]) (rs :: [u]). (rs ⊆ ss, RPureConstrained (FieldOffset f ss) rs, RPureConstrained (FieldOffset f rs) rs, RFoldMap rs, RMap rs, RApply rs, Storable (Rec f ss)) => SRec2 f f ss -> SRec2 f f rs -> SRec2 f f ss
- toSRec2 :: forall f ts. Storable (Rec f ts) => Rec f ts -> SRec2 f f ts
- fromSRec2 :: Storable (Rec f ts) => SRec2 g f ts -> Rec f ts
- newtype SRec2 (g :: k -> *) (f :: k -> *) (ts :: [k]) = SRec2 (ForeignPtr (Rec f ts))
- class FieldOffsetAux f ts t (RIndex t ts) => FieldOffset f ts t
- class (RIndex t ts ~ i, RecAll f ts Storable) => FieldOffsetAux f ts t i where
- data StorableAt f a where
- StorableAt :: Storable (f a) => !Int -> StorableAt f a

- peekField :: forall f t ts. FieldOffset f ts t => ForeignPtr (Rec f ts) -> IO (f t)
- pokeField :: forall f t ts. FieldOffset f ts t => ForeignPtr (Rec f ts) -> f t -> IO ()

# Main record lens API

A simpler type for `SRec2`

whose `RecElem`

and `RecSubset`

instances are specialized to the `ElField`

functor.

## Instances

# Lens API specialized to

`SRec2`

sput :: forall (f :: u -> *) (t :: u) (ts :: [u]). (FieldOffset f ts t, Storable (Rec f ts), AllConstrained (FieldOffset f ts) ts) => f t -> SRec2 f f ts -> SRec2 f f ts Source #

Set a field.

slens :: (Functor g, FieldOffset f ts t, Storable (Rec f ts), AllConstrained (FieldOffset f ts) ts) => (f t -> g (f t)) -> SRec2 f f ts -> g (SRec2 f f ts) Source #

A lens for a field of an `SRec2`

.

srecGetSubset :: forall (ss :: [u]) (rs :: [u]) (f :: u -> *). (RPureConstrained (FieldOffset f ss) rs, RPureConstrained (FieldOffset f rs) rs, RFoldMap rs, RMap rs, RApply rs, Storable (Rec f rs)) => SRec2 f f ss -> SRec2 f f rs Source #

Get a subset of a record's fields.

srecSetSubset :: forall (f :: u -> *) (ss :: [u]) (rs :: [u]). (rs ⊆ ss, RPureConstrained (FieldOffset f ss) rs, RPureConstrained (FieldOffset f rs) rs, RFoldMap rs, RMap rs, RApply rs, Storable (Rec f ss)) => SRec2 f f ss -> SRec2 f f rs -> SRec2 f f ss Source #

Set a subset of a record's fields.

# Internals

newtype SRec2 (g :: k -> *) (f :: k -> *) (ts :: [k]) Source #

A `Storable`

-backed `Rec`

. Each field of such a value has
statically known size, allowing for a very efficient representation
and very fast field access. The `2`

suffix is due to apparently
taking *two* functor arguments, but the first type parameter is
phantom and exists so that we can write multiple instances of
`RecElem`

and `RecSubset`

for different functors. The first functor
argument will typically be identical to the second argument. We
currently provide instances for the `ElField`

functor; if you wish
to use it at a different type, consider using `sget`

, `sput`

, and
`slens`

which work with any functor given that the necessary
`Storable`

instances exist.

## Instances

class FieldOffsetAux f ts t (RIndex t ts) => FieldOffset f ts t Source #

A more concise constraint equivalent to `FieldOffsetAux`

.

## Instances

FieldOffsetAux f ts t (RIndex t ts) => FieldOffset (f :: k -> *) (ts :: [k]) (t :: k) Source # | |

Defined in Data.Vinyl.SRec |

class (RIndex t ts ~ i, RecAll f ts Storable) => FieldOffsetAux f ts t i where Source #

fieldOffset :: Int -> StorableAt f t Source #

Get the byte offset of a field from the given origin and the
`Storable`

dictionary needed to work with that field.

## Instances

RecAll f (t ': ts) Storable => FieldOffsetAux (f :: a -> *) (t ': ts :: [a]) (t :: a) Z Source # | |

Defined in Data.Vinyl.SRec fieldOffset :: Int -> StorableAt f t Source # | |

(RIndex t (s ': ts) ~ S i, FieldOffsetAux f ts t i, RecAll f (s ': ts) Storable) => FieldOffsetAux (f :: a -> *) (s ': ts :: [a]) (t :: a) (S i) Source # | |

Defined in Data.Vinyl.SRec fieldOffset :: Int -> StorableAt f t Source # |

data StorableAt f a where Source #

Capture a `Storable`

dictionary along with a byte offset from
some origin address.

StorableAt :: Storable (f a) => !Int -> StorableAt f a |