Safe Haskell | None |
---|---|
Language | Haskell2010 |
The public interface is exported from RecordU
- newtype RecordUS x = RecordUS Any
- class RecordUSCxt x u | x -> u, u -> x where
- recordUSToHList :: RecordUS x -> HList u
- hListToRecordUS :: HList u -> RecordUS x
- data EqTagValue
- class HMapUnboxF xs us | xs -> us, us -> xs
- newtype RecordU l = RecordU (UArray Int (GetElemTy l))
- type family GetElemTy x :: *
- class SortForRecordUS x x' | x -> x' where
- sortForRecordUS :: Record x -> Record x'
- class HLookupByHNatUS n us e | n us -> e where
- hLookupByHNatUS :: Proxy n -> HList us -> e
- class HLookupByHNatUS1 r n u us e | r n u us -> e where
- hLookupByHNatUS1 :: Proxy r -> Proxy n -> RecordU u -> HList us -> e
- type family HSubtract n1 n2 :: Either HNat HNat
- 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))
- recordUS' :: (HMapUnboxF g u, HGroupBy * EqTagValue x g, Profunctor p, Functor f) => p (RecordUS x) (f (RecordUS x)) -> p (HList u) (f (HList u))
- recordToRecordUS :: forall x g u. (HMapCxt HList UnboxF g u, HMapUnboxF g u, HGroupBy EqTagValue x g, RecordUSCxt x u) => Record x -> RecordUS x
- recordUSToRecord :: forall u g x. (HConcatFD g x, HMapCxt HList BoxF u g, HMapUnboxF g u, RecordUSCxt x u) => RecordUS x -> Record x
- 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))
- 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))
- class ElemTyEq xs
- class HUpdateMany lv rx where
- hUpdateMany :: Record lv -> rx -> rx
- class HFindMany ls r ns | ls r -> ns
- hMapRU :: HMapCxt RecordU f x y => f -> RecordU x -> RecordU y
- 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)
- 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))
- class RecordToRecordU x where
- recordToRecordU :: Record x -> RecordU x
- class RecordUToRecord x where
- recordUToRecord :: RecordU x -> Record x
- type Bad = `[Tagged "x" Double, Tagged "i" Int, Tagged "y" Double, Tagged "j" Int]`
- bad :: Record Bad
- bad1 :: Record `[Tagged "x" Double, Tagged "y" Double]`
- data UnboxF = UnboxF
- data BoxF = BoxF
Type definitions
RecordUS
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.
RecordUS Any | Any here is the |
(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 |
(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.
Nothing
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
(HGroupBy * EqTagValue x g, HMapUnboxF g u) => RecordUSCxt x u | the only instance |
data EqTagValue Source
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
HMapUnboxF ([] *) ([] *) | |
HMapUnboxF xs us => HMapUnboxF ((:) * (HList x) xs) ((:) * (RecordU x) us) |
RecordU
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.
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)])]
sortForRecordUS :: Record x -> Record x' Source
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
hLookupByHNatUS :: Proxy n -> HList us -> e Source
((~) (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
(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
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)
all elements of the list have the same type
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.
hUpdateMany :: Record lv -> rx -> rx Source
(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) |
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)
class RecordToRecordU x where Source
recordToRecordU :: Record x -> RecordU x Source
(RecordValues x, HList2List (RecordValuesR x) (GetElemTy x), HNat2Integral n, HLengthEq x n, IArray UArray (GetElemTy x)) => RecordToRecordU x |
class RecordUToRecord x where Source
recordUToRecord :: RecordU x -> Record x Source
(HMapCxt HList TaggedFn (RecordValuesR x) x, IArray UArray (GetElemTy x), HList2List (RecordValuesR x) (GetElemTy x)) => RecordUToRecord x |
definitions for doctest examples
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
((~) * hx (HList x), (~) * ux (RecordU x), RecordToRecordU x) => ApplyAB UnboxF hx ux |