HList-0.4.1.0: Heterogeneous lists

Safe HaskellNone
LanguageHaskell2010

Data.HList.RecordU

Contents

Description

The public interface is exported from RecordU

Synopsis

Type definitions

RecordUS

newtype RecordUS x Source

RecordUS is stored as a HList of RecordU to allow the RecordUS to contain elements of different types, so long all of the types can be put into an unboxed array (UArray).

It is advantageous (at least space-wise) to sort the record to keep elements with the same types elements adjacent. See SortForRecordUS for more details.

Constructors

RecordUS Any

Any here is the HList u given RecordUSCxt x u

Instances

(HFindLabel k l r n, HLookupByHNatUS n u (Tagged k l v), HasField k l (Record r) v, RecordUSCxt r u) => HasField k l (RecordUS r) v

works expected. See examples attached to bad.

(RecordUSCxt x u, Show (HList u)) => Show (RecordUS x) 

class RecordUSCxt x u | x -> u, u -> x where Source

connect the unpacked x representation with the corresponding list of RecordU u representation.

Minimal complete definition

Nothing

Methods

recordUSToHList :: RecordUS x -> HList u Source

O(1) should be possible to implement this without unsafeCoerce, but we want to hide the u parameter _and_ keep the RecordUSCxt as a class (instead of a type family) because of HEq. In some cases it is possible to have instances that do not actually respect the functional dependency, but this should be safe if the check is not disabled (by using -XDysfunctionalDependencies https://phabricator.haskell.org/D69, or ghc-7.6)

hListToRecordUS :: HList u -> RecordUS x Source

O(1) should be possible to implement this without unsafeCoerce

Instances

(HGroupBy * EqTagValue x g, HMapUnboxF g u) => RecordUSCxt x u

the only instance

data EqTagValue Source

Instances

HEqByFn * EqTagValue 
((~) * txv (Tagged k x v), (~) * tyw (Tagged k1 y w), HEq * v w b) => HEqBy * * EqTagValue txv tyw b 

class HMapUnboxF xs us | xs -> us, us -> xs Source

proof that hMap UnboxF :: r xs -> r us can determine xs from us and us from xs

Instances

HMapUnboxF ([] *) ([] *) 
HMapUnboxF xs us => HMapUnboxF ((:) * (HList x) xs) ((:) * (RecordU x) us) 

RecordU

newtype RecordU l Source

A type which behaves similarly to Record, except all elements must fit in the same UArray. A consequence of this is that RecordU has the following properties:

  • it is strict in the element types
  • it cannot do type-changing updates of RecordU, except if the function applies to all elements
  • it probably is slower to update the very first elements of the RecordU

The benefit is that lookups should be faster and records should take up less space. However benchmarks done with a slow HNat2Integral do not suggest that RecordU is faster than Record.

Constructors

RecordU (UArray Int (GetElemTy l)) 

Instances

(ApplyAB f (GetElemTy x) (GetElemTy y), IArray UArray (GetElemTy y), IArray UArray (GetElemTy x)) => HMapAux RecordU f x y 
((~) [*] r r', (~) * v (GetElemTy r), HFindLabel k l r n, HNat2Integral n, IArray UArray v, HasField k l (Record r') v) => HUpdateAtLabel k RecordU l v r r' 
((~) [*] s t, (~) * a b, IArray UArray a, (~) * a (GetElemTy s), HLensCxt k x RecordU s t a b) => Labelable k x RecordU s t a b

make a Lens' (RecordU s) a

(IArray UArray v, (~) * v (GetElemTy ls), HFindLabel k l ls n, HNat2Integral n) => HasField k l (RecordU ls) v 
(RecordValues lv, HList2List (RecordValuesR lv) v, HFindMany * (LabelsOf lv) (LabelsOf r) ixs, IArray UArray v, (~) * v (GetElemTy r), HNats2Integrals ixs) => HUpdateMany lv (RecordU r) 
Eq (UArray Int (GetElemTy l)) => Eq (RecordU l) 
Ord (UArray Int (GetElemTy l)) => Ord (RecordU l) 
Read (UArray Int (GetElemTy l)) => Read (RecordU l) 
Show (UArray Int (GetElemTy l)) => Show (RecordU l) 
HMapUnboxF xs us => HMapUnboxF ((:) * (HList x) xs) ((:) * (RecordU x) us) 
type LabelableTy RecordU = LabelableLens 

type family GetElemTy x :: * Source

Instances

type GetElemTy ((:) * (Tagged k label v) rest) = v 

class SortForRecordUS x x' | x -> x' where Source

Reorders a Record such that the RecordUS made from it takes up less space

Bad has alternating Double and Int fields

>>> bad
Record{x=1.0,i=2,y=3.0,j=4}

4 arrays containing one element each are needed when this Record is stored as a RecordUS

>>> recordToRecordUS bad
RecordUS H[RecordU (array (0,0) [(0,1.0)]),RecordU (array (0,0) [(0,2)]),RecordU (array (0,0) [(0,3.0)]),RecordU (array (0,0) [(0,4)])]

It is possible to sort the record

>>> sortForRecordUS bad
Record{x=1.0,y=3.0,i=2,j=4}

This allows the same content to be stored in two unboxed arrays

>>> recordToRecordUS (sortForRecordUS bad)
RecordUS H[RecordU (array (0,1) [(0,1.0),(1,3.0)]),RecordU (array (0,1) [(0,2),(1,4)])]

Instances

SortForRecordUS ([] *) ([] *) 
(HPartitionEq * * EqTagValue x ((:) * x xs) xi xo, SortForRecordUS xo xo', (~) [*] sorted (HAppendListR * xi xo'), HAppendList xi xo') => SortForRecordUS ((:) * x xs) sorted 

Lookup

class HLookupByHNatUS n us e | n us -> e where Source

Methods

hLookupByHNatUS :: Proxy n -> HList us -> e Source

Instances

((~) (Either HNat HNat) r (HSubtract (HLength * u) n), (~) * (RecordU u) ru, HLookupByHNatUS1 r n u us e) => HLookupByHNatUS n ((:) * ru us) e 

class HLookupByHNatUS1 r n u us e | r n u us -> e where Source

Methods

hLookupByHNatUS1 :: Proxy r -> Proxy n -> RecordU u -> HList us -> e Source

Instances

(HNat2Integral n, (~) * (HLookupByHNatR n u) le, (~) * le (Tagged k l e), IArray UArray e, (~) * e (GetElemTy u)) => HLookupByHNatUS1 (Left HNat HNat t) n u us le 
HLookupByHNatUS t us e => HLookupByHNatUS1 (Right HNat HNat t) n u us e 

type family HSubtract n1 n2 :: Either HNat HNat Source

HSubtract a b is Left (a-b), Right (b-a) or Right HZero

Instances

Conversion of RecordUS

with the actual representation

recordUS :: (HMapUnboxF g1 u1, HMapUnboxF g u, HGroupBy * EqTagValue x1 g1, HGroupBy * EqTagValue x g, Profunctor p, Functor f) => p (RecordUS x) (f (RecordUS x1)) -> p (HList u) (f (HList u1)) Source

Iso (HList s) (HList t) (RecordUS a) (Record b)

recordUS' :: (HMapUnboxF g u, HGroupBy * EqTagValue x g, Profunctor p, Functor f) => p (RecordUS x) (f (RecordUS x)) -> p (HList u) (f (HList u)) Source

Iso (HList s) (RecordUS a)

s is a HList of RecordU while a :: [*] is list of Tagged label value

with Record

recordToRecordUS :: forall x g u. (HMapCxt HList UnboxF g u, HMapUnboxF g u, HGroupBy EqTagValue x g, RecordUSCxt x u) => Record x -> RecordUS x Source

view unboxedS or ^. unboxedS are preferred

recordUSToRecord :: forall u g x. (HConcatFD g x, HMapCxt HList BoxF u g, HMapUnboxF g u, RecordUSCxt x u) => RecordUS x -> Record x Source

^. from unboxedS is preferred

unboxedS :: (HMapUnboxF g1 u1, HMapUnboxF g u, HConcatFD g1 x1, HMapAux HList UnboxF g u, HMapAux HList BoxF u1 g1, HGroupBy * EqTagValue x1 g1, HGroupBy * EqTagValue x g, SameLength' * * g1 u1, SameLength' * * g u, SameLength' * * u1 g1, SameLength' * * u g, Profunctor p, Functor f) => p (RecordUS x) (f (RecordUS x1)) -> p (Record x) (f (Record x1)) Source

Iso (Record x) (Record y) (RecordUS x) (RecordUS y)

unboxedS' :: (HMapUnboxF g u, HConcatFD g x, HMapAux HList UnboxF g u, HMapAux HList BoxF u g, HGroupBy * EqTagValue x g, SameLength' * * g u, SameLength' * * u g, Profunctor p, Functor f) => p (RecordUS x) (f (RecordUS x)) -> p (Record x) (f (Record x)) Source

Iso' (Record x) (RecordUS x)

class ElemTyEq xs Source

all elements of the list have the same type

Instances

ElemTyEq ([] *) 
(~) * t1v (Tagged k t v) => ElemTyEq ((:) * t1v rest) 
((~) * t1v (Tagged k t1 v), (~) * t2v (Tagged k1 t2 v), ElemTyEq ((:) * tv2 rest)) => ElemTyEq ((:) * tv1 ((:) * tv2 rest)) 

class HUpdateMany lv rx where Source

analogous flip //. Similar to .<++., except it is restricted to cases where the left argument holds a subset of elements.

Methods

hUpdateMany :: Record lv -> rx -> rx Source

Instances

(HLeftUnion lv x lvx, HRLabelSet x, HLabelSet [*] (LabelsOf x), HRearrange (LabelsOf x) lvx x) => HUpdateMany lv (Record x)

implementation in terms of .<++.

(RecordValues lv, HList2List (RecordValuesR lv) v, HFindMany * (LabelsOf lv) (LabelsOf r) ixs, IArray UArray v, (~) * v (GetElemTy r), HNats2Integrals ixs) => HUpdateMany lv (RecordU r) 

class HFindMany ls r ns | ls r -> ns Source

behaves like map HFind

Instances

HFindMany k ([] k) r ([] HNat) 
(HFind k l r n, HFindMany k ls r ns) => HFindMany k ((:) k l ls) r ((:) HNat n ns) 

hMapRU :: HMapCxt RecordU f x y => f -> RecordU x -> RecordU y Source

hMap specialized to RecordU

unboxed :: forall x y f p. (Profunctor p, Functor f, RecordToRecordU x, RecordUToRecord y) => (RecordU x `p` f (RecordU y)) -> Record x `p` f (Record y) Source

Iso (Record x) (Record y) (RecordU x) (RecordU y)

unboxed' :: (RecordValues x, HMapAux HList TaggedFn (RecordValuesR x) x, HList2List (RecordValuesR x) (GetElemTy x), HLengthEq1 HNat x n, HLengthEq2 HNat x n, SameLength' * * (HReplicateR * n ()) x, Profunctor p, IArray UArray (GetElemTy x), KnownNat (HNat2Nat n), Functor f) => p (RecordU x) (f (RecordU x)) -> p (Record x) (f (Record x)) Source

Iso' (Record x) (RecordU x)

definitions for doctest examples

type Bad = `[Tagged "x" Double, Tagged "i" Int, Tagged "y" Double, Tagged "j" Int]` Source

bad :: Record Bad Source

HasField instances

RecordUS
>>> let r = recordToRecordUS (sortForRecordUS bad)
>>> let s = recordToRecordUS bad
>>> let x = Label :: Label "x"
>>> let y = Label :: Label "y"
>>> let i = Label :: Label "i"
>>> let j = Label :: Label "j"
>>> (r .!. x, r .!. i, r .!. y, r .!. j)
(1.0,2,3.0,4)
>>> (s .!. x, s .!. i, s .!. y, s .!. j)
(1.0,2,3.0,4)
RecordU
>>> let t = recordToRecordU bad1
>>> (t .!. x, t .!. y)
(1.0,2.0)
>>> hUpdateAtLabel x 3 t .!. x
3.0

Implementation Details

data UnboxF Source

Constructors

UnboxF 

Instances

((~) * hx (HList x), (~) * ux (RecordU x), RecordToRecordU x) => ApplyAB UnboxF hx ux 

data BoxF Source

Constructors

BoxF 

Instances

((~) * ux (RecordU x), (~) * hx (HList x), RecordUToRecord x) => ApplyAB BoxF ux hx