HList-0.4.1.0: Heterogeneous lists

Safe HaskellNone
LanguageHaskell2010

Data.HList.HListPrelude

Description

The HList library

(C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke

Declarations for various classes and functions that apply for the whole range of heterogeneous collections (HList, TIP, records, etc).

Synopsis

Documentation

class HExtend e l where Source

Associated Types

type HExtendR e l Source

Methods

(.*.) :: e -> l -> HExtendR e l infixr 2 Source

Instances

HExtend e (HList l) 
HRLabelSet ((:) * t r) => HExtend t (Record r) 
(HRLabelSet ((:) * (Tagged * e e) l), HTypeIndexed l) => HExtend e (TIP l) 
((~) * le (Tagged k l (Maybe e)), HOccursNot * (Label k l) (LabelsOf v)) => HExtend le (Variant v)

Extension for Variants prefers the first value

(l .=. Nothing) .*. v = v
(l .=. Just e)  .*. _ = mkVariant l e Proxy
((~) * me (Maybe e), HOccursNot * (Tagged * e e) l) => HExtend me (TIC l)
Nothing .*. x = x
Just a .*. y = mkTIC a
((~) (* -> * -> *) to (LabeledTo Symbol x), ToSym (to p q) x) => HExtend (to p q) (Proxy [*] ((:) * (Lbl n ns desc) xs))

if the proxy has Data.HList.Label3.Lbl, then everything has to be wrapped in Label to make the kinds match up.

((~) (* -> * -> *) to (LabeledTo Symbol x), ToSym (to p q) x) => HExtend (to p q) (Proxy [Symbol] ((:) Symbol x xs)) 
((~) (* -> * -> *) to (LabeledTo Symbol x), ToSym (to p q) x) => HExtend (to p q) (Proxy [*] ([] *))

Together with the instance below, this allows writing

makeLabelable "x y z"
p = x .*. y .*. z .*. emptyProxy

Or with HListPP

p = `x .*. `y .*. `z .*. emptyProxy

instead of

p = Proxy :: Proxy ["x","y","z"]
HExtend (Label * (Lbl n ns desc)) (Proxy [Symbol] ((:) Symbol x xs))

Mixing two label kinds means we have to include Label:

>>> let r = label3 .*. label6 .*. emptyProxy
>>> :t r
r :: Proxy '[Label (Lbl 'HZero () ()), Label "6"]
HExtend (Label * (Lbl n ns desc)) (Proxy [*] ((:) * (Lbl n' ns' desc') xs))

If possible, Label is left off:

>>> let q = label3 .*. label3 .*. emptyProxy
>>> :t q
q :: Proxy '[Lbl 'HZero () (), Lbl 'HZero () ()]
HExtend (Label Nat y) (Proxy [Symbol] ((:) Symbol x xs)) 
HExtend (Label Nat y) (Proxy [*] ((:) * x xs)) 
HExtend (Label Nat y) (Proxy [Nat] ((:) Nat x xs)) 
HExtend (Label Symbol y) (Proxy [Nat] ((:) Nat x xs)) 
HExtend (Label Symbol y) (Proxy [*] ((:) * x xs))

Mixing two label kinds means we have to include Label:

>>> let s = label6 .*. label3 .*. emptyProxy
>>> :t s
s :: Proxy '[Label "6", Label (Lbl 'HZero () ())]
HExtend (Label Symbol y) (Proxy [Symbol] ((:) Symbol x xs))
>>> let labelX = Label :: Label "x"
>>> let labelY = Label :: Label "y"
>>> let p = labelX .*. labelY .*. emptyProxy
>>> :t p
p :: Proxy '["x", "y"]
HExtend (Label k x) (Proxy [*] ([] *))

to keep types shorter, .*. used with Proxy avoids producing a Proxy :: Proxy '[Label x,Label y,Label z] if Proxy :: Proxy '[x,y,z] is not a kind error (as it is when mixing Label6 and Label3 labels).

ghc-7.6 does not accept Proxy ('[] :: [k]) so for now require k ~ *

emptyProxy :: Proxy [*] ([] *) Source

similar to emptyRecord, emptyTIP, emptyHList (actually called HNil), except emptyProxy is the rightmost argument to .*.

class SubType l l' Source

Instances

H2ProjectByLabels (LabelsOf r2) r1 r2 rout => SubType * * (Record r1) (Record r2)

Subtyping for records

(HOccurs e (TIP l1), SubType * * (TIP l1) (TIP l2)) => SubType * * (TIP l1) (TIP ((:) * e l2)) 
SubType * * (TIP l) (TIP ([] *))

Subtyping for TIPs

class HAppend l1 l2 where Source

Methods

hAppend :: l1 -> l2 -> HAppendR l1 l2 Source

Instances

HAppendList l1 l2 => HAppend (HList l1) (HList l2) 
(HRLabelSet (HAppendListR * r1 r2), HAppend (HList r1) (HList r2)) => HAppend (Record r1) (Record r2)
(.*.)
Add a field to a record. Analagous to (++) for lists.
record .*. field1
       .*. field2
(HAppend (HList l) (HList l'), HTypeIndexed (HAppendListR * l l')) => HAppend (TIP l) (TIP l') 

type family HAppendR l1 l2 :: k Source

poly-kinded, but hAppend only works in cases where the kind variable k is *

Instances

type HAppendR * (HList l1) (HList l2) = HList (HAppendListR * l1 l2) 
type HAppendR * (Record r1) (Record r2) = Record (HAppendListR * r1 r2) 
type HAppendR * (TIP l) (TIP l') = TIP (HAppendListR * l l') 

class HOccurs e l where Source

Methods

hOccurs :: l -> e Source

Instances

(HOccurrence e ((:) * x y) l', HOccurs' e l') => HOccurs e (HList ((:) * x y)) 
HasField * e (Record ((:) * x ((:) * y l))) e => HOccurs e (TIP ((:) * x ((:) * y l))) 
(~) * tee (Tagged * e e) => HOccurs e (TIP ((:) * tee ([] *)))

One occurrence and nothing is left

This variation provides an extra feature for singleton lists. That is, the result type is unified with the element in the list. Hence the explicit provision of a result type can be omitted.

(HasField * o (TIC l) mo, (~) * mo (Maybe o)) => HOccurs mo (TIC l) 

class HOccursNot e l Source

Instances

HOccursNot * e ([] *) 
(HEq * e e1 b, HOccursNot' * b e l) => HOccursNot * e ((:) * e1 l) 

class HProject l l' where Source

Methods

hProject :: l -> l' Source

Instances

(HOccurs e l, HProject l (HList l')) => HProject l (HList ((:) * e l')) 
HProject (HList l) (HList ([] *)) 

class HType2HNat e l n | e l -> n Source

Map a type (key) to a natural (index) within the collection This is a purely type-level computation

Instances

(HEq * e1 e b, HType2HNatCase b e1 l n) => HType2HNat * e1 ((:) * e l) n

Map a type to a natural (index within the collection) This is a purely type-level computation

class HTypes2HNats es l ns | es l -> ns Source

Instances

HTypes2HNats [*] [*] ([] *) l ([] HNat)

And lift to the list of types

(HType2HNat * e l n, HTypes2HNats [*] [*] es l ns) => HTypes2HNats [*] [*] ((:) * e es) l ((:) HNat n ns) 

class HDeleteMany e l l' | e l -> l' where Source

Delete all elements with the type-level key e from the collection l. Since the key is type-level, it is represented by a Proxy. (polykinded)

Methods

hDeleteMany :: Proxy e -> l -> l' Source

Instances

(HEq * e1 e b, HDeleteManyCase * b e1 e l l1) => HDeleteMany * e1 (HList ((:) * e l)) (HList l1) 
HDeleteMany k e (HList ([] *)) (HList ([] *)) 

class HDeleteAtLabel r l v v' | l v -> v' where Source

Methods

hDeleteAtLabel :: Label l -> r v -> r v' Source

Instances

(HDeleteAtHNat n l, HType2HNat * e l n, (~) [*] l' (HDeleteAtHNatR n l)) => HDeleteAtLabel * HList e l l'

should this instead delete the first element of that type?

H2ProjectByLabels ((:) * (Label k l) ([] *)) v t1 v' => HDeleteAtLabel k Record l v v' 
(HDeleteAtLabel k Record e v v', HTypeIndexed v') => HDeleteAtLabel k TIP e v v' 

class SameLengths `[x, y, xy]` => HUnzip r x y xy | x y -> xy, xy -> x y where Source

Methods

hUnzip :: r xy -> (r x, r y) Source

Instances

(SameLengths * ((:) [*] x ((:) [*] y ((:) [*] xy ([] [*])))), HZipList x y xy) => HUnzip HList x y xy 
(HZipRecord x y xy, SameLengths * ((:) [*] x ((:) [*] y ((:) [*] xy ([] [*]))))) => HUnzip Record x y xy 
(HZipList (UntagR x) (UntagR y) (UntagR xy), UntagTag x, UntagTag y, UntagTag xy, HTypeIndexed x, HTypeIndexed y, SameLengths * ((:) [*] x ((:) [*] y ((:) [*] xy ([] [*]))))) => HUnzip TIP x y xy 
(Unvariant ((:) * txy ([] *)) txy, (~) * tx (Tagged k t x), (~) * ty (Tagged k t y), (~) * txy (Tagged k t (x, y))) => HUnzip Variant ((:) * tx ([] *)) ((:) * ty ([] *)) ((:) * txy ([] *)) 
(HUnzip Variant ((:) * x2 xs) ((:) * y2 ys) ((:) * xy2 xys), (~) * tx (Tagged k t x), (~) * ty (Tagged k t y), (~) * txy (Tagged k t (x, y))) => HUnzip Variant ((:) * tx ((:) * x2 xs)) ((:) * ty ((:) * y2 ys)) ((:) * txy ((:) * xy2 xys)) 
((~) [*] (RecordValuesR lvs) vs, SameLabels [*] [*] ls lvs, (~) [*] (LabelsOf lvs) ls, SameLengths * ((:) [*] ls ((:) [*] vs ((:) [*] lvs ([] [*])))), HAllTaggedLV lvs) => HUnzip (Proxy [*]) ls vs lvs 

class HUnzip r x y xy => HZip r x y xy where Source

zip. Variant supports hUnzip, but not hZip (hZipVariant returns a Maybe)

Methods

hZip :: r x -> r y -> r xy Source

Instances

(SameLengths * ((:) [*] x ((:) [*] y ((:) [*] xy ([] [*])))), HZipList x y xy) => HZip HList x y xy 
(HZipRecord x y xy, SameLengths * ((:) [*] x ((:) [*] y ((:) [*] xy ([] [*]))))) => HZip Record x y xy
>>> let x :: Record '[Tagged "x" Int]; x = undefined
>>> let y :: Record '[Tagged "x" Char]; y = undefined
>>> :t hZip x y
hZip x y :: Record '[Tagged "x" (Int, Char)]
(HZipList (UntagR x) (UntagR y) (UntagR xy), UntagTag x, UntagTag y, UntagTag xy, SameLengths * ((:) [*] x ((:) [*] y ((:) [*] xy ([] [*])))), HTypeIndexed x, HTypeIndexed y, HUnzip TIP x y xy) => HZip TIP x y xy 
HUnzip (Proxy [*]) ls vs lvs => HZip (Proxy [*]) ls vs lvs