HList-0.2.3: Heterogeneous lists

Safe HaskellNone

Data.HList.Record

Contents

Description

The HList library

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

Extensible records

The are different models of labels that go with this module; see:

Synopsis

Records

Labels

Record types as label-value pairs, where label is purely phantom. Thus the run-time representation of a field is the same as that of its value, and the record, at run-time, is indistinguishable from the HList of field values. At run-time, all information about the labels is erased.

newtype LVPair l v

Field of label l with value type v

Constructors

LVPair 

Fields

valueLVPair :: v
 

Instances

HasField' HTrue l (HCons (LVPair l v) r) v 
(UnionSymRec r1 r2' (Record ru), HasField l2 ru v2, HUpdateAtHNat n (LVPair l2 v2) ru ru, RecordLabels ru ls, HFind l2 ls n) => UnionSymRec' HTrue r1 (LVPair l2 v2) r2' (Record ru)

Field f2 is already in r1, so it will be in the union of r1 with the rest of r2.

To inject (HCons f2 r2) in that union, we should replace the field f2

HRearrange ls rout r' => HRearrange' l ls (HCons (LVPair l v) HNil) rout (HCons (LVPair l v) r') 
(Narrow rout r', H2ProjectByLabels (HCons l HNil) r (HCons (LVPair l v) HNil) rout) => Narrow r (HCons (LVPair l v) r') 
(HEq l l' b, HasField' b l (HCons (LVPair l' v') r) v) => HasField l (HCons (LVPair l' v') r) v 
(H2ProjectByLabels (HCons l HNil) a rin rout, NarrowM' rin rout b res) => NarrowM a (HCons (LVPair l v) b) res 
Fail (ExtraField l) => HRearrange HNil (HCons (LVPair l v) a) (ExtraField l)

For improved error messages

(RecordLabels r1 ls, HMember l ls b, UnionSymRec' b (Record r1) (LVPair l v) (Record r2') ru) => UnionSymRec (Record r1) (Record (HCons (LVPair l v) r2')) ru 
(RecordLabels r ls, HMember l ls b, HLeftUnionBool b r (LVPair l v) r''', HLeftUnion (Record r''') (Record r') r'') => HLeftUnion (Record r) (Record (HCons (LVPair l v) r')) r'' 
Eq v => Eq (LVPair l v) 
(Typeable x, Typeable y) => Typeable (LVPair x y) 
(ShowLabel l, Show v, ShowComponents r) => ShowComponents (HCons (LVPair l v) r) 
(HEq l1 l2 leq, HRLabelSet' l1 v1 l2 v2 leq r) => HRLabelSet (HCons (LVPair l1 v1) (HCons (LVPair l2 v2) r)) 
Fail (ProxyFound x) => HasNoProxies (HCons (LVPair lab (Proxy x)) l) 
HRLabelSet (HCons (LVPair l v) r) => HExtend (LVPair l v) (Record r) (Record (HCons (LVPair l v) r)) 
RecordValues r' vs => RecordValues (HCons (LVPair l v) r') (HCons v vs) 
RecordLabels r' ls => RecordLabels (HCons (LVPair l v) r') (HCons l ls) 
HMaybied r r' => HMaybied (HCons (LVPair l (Proxy v)) r) (HCons (LVPair l (Maybe v)) r') 
(HMemberM l' (HCons l ls) b, H2ProjectByLabels' b (HCons l ls) (HCons (LVPair l' v') r') rin rout) => H2ProjectByLabels (HCons l ls) (HCons (LVPair l' v') r') rin rout 
(HLabelSet (HCons l ls), HSameLength ls vs) => HExtend (LVPair l v) (RecordP ls vs) (RecordP (HCons l ls) (HCons v vs)) 
(RecordR2P r ls vs, HRLabelSet (HCons (LVPair l v) r), HLabelSet (HCons l ls), HSameLength ls vs) => RecordR2P (HCons (LVPair l v) r) (HCons l ls) (HCons v vs) 

labelLVPair :: LVPair l v -> l

Label accessor

newLVPair :: l -> v -> LVPair l v

Record

newtype Record r

Constructors

Record r 

Instances

(UnionSymRec r1 r2' (Record ru), HExtend f2 (Record ru) (Record (HCons f2 ru))) => UnionSymRec' HFalse r1 f2 r2' (Record (HCons f2 ru)) 
NarrowM a HNil (HJust (Record HNil)) 
(UnionSymRec r1 r2' (Record ru), HasField l2 ru v2, HUpdateAtHNat n (LVPair l2 v2) ru ru, RecordLabels ru ls, HFind l2 ls n) => UnionSymRec' HTrue r1 (LVPair l2 v2) r2' (Record ru)

Field f2 is already in r1, so it will be in the union of r1 with the rest of r2.

To inject (HCons f2 r2) in that union, we should replace the field f2

UnionSymRec r1 (Record HNil) r1 
HLeftUnion r (Record HNil) r 
HasField l r v => HasField l (Record r) v 
NarrowM'' f (HJust (Record r)) (HJust (Record (HCons f r))) 
Eq r => Eq (Record r) 
ShowComponents r => Show (Record r) 
Typeable x => Typeable (Record x) 
(RecordLabels r' ls, H2ProjectByLabels ls r r' rout) => SubType (Record r) (Record r')

Subtyping for records

(RecordLabels r1 ls, HMember l ls b, UnionSymRec' b (Record r1) (LVPair l v) (Record r2') ru) => UnionSymRec (Record r1) (Record (HCons (LVPair l v) r2')) ru 
(RecordLabels r ls, HMember l ls b, HLeftUnionBool b r (LVPair l v) r''', HLeftUnion (Record r''') (Record r') r'') => HLeftUnion (Record r) (Record (HCons (LVPair l v) r')) r'' 
(HRLabelSet r'', HAppend r r' r'') => HAppend (Record r) (Record r') (Record r'') 
(RecordLabels a la, RecordLabels b lb, HTIntersect la lb lc, H2ProjectByLabels lc a c aout, H2ProjectByLabels lc b c bout, HRLabelSet c) => LubNarrow (Record a) (Record b) (Record c) 
HRLabelSet (HCons (LVPair l v) r) => HExtend (LVPair l v) (Record r) (Record (HCons (LVPair l v) r)) 

mkRecord :: HRLabelSet r => r -> Record r

Build a record

emptyRecord :: Record HNil

Build an empty record

Getting Labels

class RecordLabels r ls | r -> ls

Construct the (phantom) list of labels of the record.

This is a purely type-level function.

Instances

recordLabels :: RecordLabels r ls => Record r -> ls

recordLabels' :: RecordLabels r ls => r -> ls

Getting Values

class RecordValues r ls | r -> ls where

Construct the list of values of the record.

Methods

recordValues' :: r -> ls

Instances

recordValues :: RecordValues r vs => Record r -> vs

Operations

Show

A corresponding Show instance exists as

 show x = "Record {" ++ showComponents "" x ++ "}"

class ShowComponents l where

Methods

showComponents :: String -> l -> String

class ShowLabel l where

Methods

showLabel :: l -> String

Instances

Typeable x => ShowLabel x

Show label

Typeable x => ShowLabel (Proxy x)

Show label

Show n => ShowLabel (Label n)

Show label

(HNat x, Show desc) => ShowLabel (Label x ns desc)

Show label

(HNat x, Show desc) => ShowLabel (Label x ns desc)

Show label

Lookup

class HasField l r v | l r -> v where

This is a baseline implementation. We use a helper class, HasField, to abstract from the implementation.

Because hLookupByLabel is so frequent and important, we implement it separately, more efficiently. The algorithm is familiar assq, only the comparison operation is done at compile-time

Methods

hLookupByLabel :: l -> r -> v

Instances

HasField l r v => HasField l (Record r) v 
(HEq l l' b, HasField' b l (HCons (LVPair l' v') r) v) => HasField l (HCons (LVPair l' v') r) v 
(HEq l l' b, HasFieldP' b l (RecordP (HCons l' ls) vs) v) => HasField l (RecordP (HCons l' ls) vs) v 

class HasField' b l r v | b l r -> v where

Methods

hLookupByLabel' :: b -> l -> r -> v

Instances

HasField l r v => HasField' HFalse l (HCons fld r) v 
HasField' HTrue l (HCons (LVPair l v) r) v 

Delete

hDeleteAtLabel label record

hDeleteAtLabel :: H2ProjectByLabels (HCons e HNil) t t1 t2 => e -> Record t -> Record t2

Update

hUpdateAtLabel label value record

hUpdateAtLabel :: (HUpdateAtHNat n (LVPair l v) t l', HFind l ls n, RecordLabels t ls) => l -> v -> Record t -> Record l'

hTPupdateAtLabel :: (HasField l t a, HUpdateAtHNat n (LVPair l a) t l', HFind l ls n, RecordLabels t ls) => l -> a -> Record t -> Record l'

We could also say:

 hTPupdateAtLabel l v r = hUpdateAtLabel l v r `asTypeOf` r

Then we were taking a dependency on Haskell's type equivalence. This would also constrain the actual implementation of hUpdateAtLabel.

A variation on hUpdateAtLabel: type-preserving update.

Rename Label

hRenameLabel :: (HRLabelSet (HCons (LVPair l v) t2), HasField e t1 v, H2ProjectByLabels (HCons e HNil) t1 t t2) => e -> l -> Record t1 -> Record (HCons (LVPair l v) t2)

Rename the label of record

Projection

It is also an important operation: the basis of many deconstructors -- so we try to implement it efficiently.

hProjectByLabels :: (HRLabelSet a, H2ProjectByLabels ls t a b) => ls -> Record t -> Record a

hProjectByLabels ls r returns r with only the labels in ls remaining

Unions

Left

class HLeftUnion r r' r'' | r r' -> r'' where

Methods

hLeftUnion :: r -> r' -> r''

Instances

HLeftUnion r (Record HNil) r 
(RecordLabels r ls, HMember l ls b, HLeftUnionBool b r (LVPair l v) r''', HLeftUnion (Record r''') (Record r') r'') => HLeftUnion (Record r) (Record (HCons (LVPair l v) r')) r'' 

class HLeftUnionBool b r f r' | b r f -> r' where

Methods

hLeftUnionBool :: b -> r -> f -> r'

Instances

Symmetric

Compute the symmetric union of two records r1 and r2 and return the pair of records injected into the union (ru1, ru2).

To be more precise, we compute the symmetric union type ru of two record types r1 and r2. The emphasis on types is important.

The two records (ru1,ru2) in the result of unionSR have the same type ru, but they are generally different values. Here the simple example: suppose

  r1 = (Label .=. True)  .*. emptyRecord
  r2 = (Label .=. False) .*. emptyRecord

Then unionSR r1 r2 will return (r1,r2). Both components of the result are different records of the same type.

To project from the union ru, use hProjectByLabels. It is possible to project from the union obtaining a record that was not used at all when creating the union.

We do assure however that if unionSR r1 r2 gave (r1u,r2u), then projecting r1u onto the type of r1 gives the value identical to r1. Ditto for r2.

class UnionSymRec r1 r2 ru | r1 r2 -> ru where

Methods

unionSR :: r1 -> r2 -> (ru, ru)

Instances

UnionSymRec r1 (Record HNil) r1 
(RecordLabels r1 ls, HMember l ls b, UnionSymRec' b (Record r1) (LVPair l v) (Record r2') ru) => UnionSymRec (Record r1) (Record (HCons (LVPair l v) r2')) ru 

Reorder Labels

hRearrange :: (HLabelSet ls, HRearrange ls r r') => ls -> Record r -> Record r'

Rearranges a record by labels. Returns the record r, rearranged such that the labels are in the order given by ls. (recordLabels r) must be a permutation of ls.

Extension

Unclassified

Probably internals, that may not be useful

data DuplicatedLabel l

Constructors

DuplicatedLabel l 

data ExtraField l

Constructors

ExtraField 

Instances

Fail (ExtraField l) => HRearrange HNil (HCons (LVPair l v) a) (ExtraField l)

For improved error messages

data FieldNotFound l

Constructors

FieldNotFound 

Instances

Fail (FieldNotFound l) => HRearrange' l ls HNil rout (FieldNotFound l)

For improved error messages

class H2ProjectByLabels ls r rin rout | ls r -> rin rout where

Invariant:

 r === rin `disjoint-union` rout
 labels rin === ls
     where (rin,rout) = hProjectByLabels ls r

Methods

h2projectByLabels :: ls -> r -> (rin, rout)

Instances

H2ProjectByLabels HNil r HNil r 
(HMember l' ls b, H2ProjectByLabels' b ls (RecordP (HCons l' ls') vs') rin rout) => H2ProjectByLabels ls (RecordP (HCons l' ls') vs') rin rout 
H2ProjectByLabels (HCons l ls) HNil HNil HNil 
(HMemberM l' (HCons l ls) b, H2ProjectByLabels' b (HCons l ls) (HCons (LVPair l' v') r') rin rout) => H2ProjectByLabels (HCons l ls) (HCons (LVPair l' v') r') rin rout 
H2ProjectByLabels (HCons l ls) (RecordP HNil HNil) (RecordP HNil HNil) (RecordP HNil HNil) 

class H2ProjectByLabels' b ls r rin rout | b ls r -> rin rout where

Methods

h2projectByLabels' :: b -> ls -> r -> (rin, rout)

Instances

H2ProjectByLabels ls r' rin rout => H2ProjectByLabels' HNothing ls (HCons f' r') rin (HCons f' rout) 
H2ProjectByLabels ls (RecordP ls' vs') rin (RecordP lo vo) => H2ProjectByLabels' HFalse ls (RecordP (HCons l' ls') (HCons v' vs')) rin (RecordP (HCons l' lo) (HCons v' vo)) 
H2ProjectByLabels ls (RecordP ls' vs') (RecordP lin vin) rout => H2ProjectByLabels' HTrue ls (RecordP (HCons l' ls') (HCons v' vs')) (RecordP (HCons l' lin) (HCons v' vin)) rout 
H2ProjectByLabels ls' r' rin rout => H2ProjectByLabels' (HJust ls') ls (HCons f' r') (HCons f' rin) rout 

class HLabelSet ls

Instances

HLabelSet HNil 
(HMember x ls xmem, HLabelSet' x ls xmem) => HLabelSet (HCons x ls) 

class HLabelSet' x ls xmem

Instances

class HRLabelSet ps

Propery of a proper label set for a record: no duplication of labels

Instances

HRLabelSet HNil 
HRLabelSet (HCons x HNil) 
(HEq l1 l2 leq, HRLabelSet' l1 v1 l2 v2 leq r) => HRLabelSet (HCons (LVPair l1 v1) (HCons (LVPair l2 v2) r)) 

class HRLabelSet' l1 v1 l2 v2 leq r

Instances

Fail (DuplicatedLabel l1) => HRLabelSet' l1 v1 l2 v2 HTrue r 
(HRLabelSet (HCons (LVPair l2 v2) r), HRLabelSet (HCons (LVPair l1 v1) r)) => HRLabelSet' l1 v1 l2 v2 HFalse r 

class HRearrange ls r r' | ls r -> r' where

Helper class for hRearrange

Methods

hRearrange2 :: ls -> r -> r'

Instances

HRearrange HNil HNil HNil 
Fail (ExtraField l) => HRearrange HNil (HCons (LVPair l v) a) (ExtraField l)

For improved error messages

(H2ProjectByLabels (HCons l HNil) r rin rout, HRearrange' l ls rin rout r') => HRearrange (HCons l ls) r r' 

class HRearrange' l ls rin rout r' | l ls rin rout -> r' where

Helper class 2 for hRearrange

Methods

hRearrange2' :: l -> ls -> rin -> rout -> r'

Instances

Fail (FieldNotFound l) => HRearrange' l ls HNil rout (FieldNotFound l)

For improved error messages

HRearrange ls rout r' => HRearrange' l ls (HCons (LVPair l v) HNil) rout (HCons (LVPair l v) r') 

class UnionSymRec' b r1 f2 r2' ru | b r1 f2 r2' -> ru where

Methods

unionSR' :: b -> r1 -> f2 -> r2' -> (ru, ru)

Instances

(UnionSymRec r1 r2' (Record ru), HExtend f2 (Record ru) (Record (HCons f2 ru))) => UnionSymRec' HFalse r1 f2 r2' (Record (HCons f2 ru)) 
(UnionSymRec r1 r2' (Record ru), HasField l2 ru v2, HUpdateAtHNat n (LVPair l2 v2) ru ru, RecordLabels ru ls, HFind l2 ls n) => UnionSymRec' HTrue r1 (LVPair l2 v2) r2' (Record ru)

Field f2 is already in r1, so it will be in the union of r1 with the rest of r2.

To inject (HCons f2 r2) in that union, we should replace the field f2