HList-0.5.0.0: Heterogeneous lists

Copyright(C) 2004 Oleg Kiselyov Ralf Laemmel Keean Schupke
Safe HaskellNone
LanguageHaskell2010

Data.HList.CommonMain

Contents

Description

The HList library

This module re-exports everything needed to use HList.

Synopsis

Faking dependent types in Haskell

Functions for all collections

Array-like access to HLists

Result-type-driven operations

Type-indexed operations

Record

quasiquoter pun helps to avoid needing a proxy value with type Label in the first place: when you take values out of or into records with pattern matching, the variable name determines the label name.

Unpacked / Unboxed Records

data 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.

Instances

(ApplyAB f (GetElemTy x) (GetElemTy y), IArray UArray (GetElemTy y), IArray UArray (GetElemTy x)) => HMapAux RecordU f x y Source # 

Methods

hMapAux :: f -> RecordU x -> RecordU y Source #

((~) [*] 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' Source # 

Methods

hUpdateAtLabel :: Label RecordU v -> r -> l r' -> l r' Source #

((~) [*] 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 Source #

make a Lens' (RecordU s) a

Associated Types

type LabelableTy (s :: [*] -> *) :: LabeledOpticType Source #

Methods

hLens' :: Label x RecordU -> LabeledOptic x RecordU s t a b b Source #

(IArray UArray v, (~) * v (GetElemTy ls), HFindLabel k l ls n, HNat2Integral n) => HasField k l (RecordU ls) v Source # 

Methods

hLookupByLabel :: Label l (RecordU ls) -> v -> v Source #

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

Methods

hUpdateMany :: Record lv -> RecordU r -> RecordU r Source #

Eq (UArray Int (GetElemTy l)) => Eq (RecordU l) Source # 

Methods

(==) :: RecordU l -> RecordU l -> Bool #

(/=) :: RecordU l -> RecordU l -> Bool #

Ord (UArray Int (GetElemTy l)) => Ord (RecordU l) Source # 

Methods

compare :: RecordU l -> RecordU l -> Ordering #

(<) :: RecordU l -> RecordU l -> Bool #

(<=) :: RecordU l -> RecordU l -> Bool #

(>) :: RecordU l -> RecordU l -> Bool #

(>=) :: RecordU l -> RecordU l -> Bool #

max :: RecordU l -> RecordU l -> RecordU l #

min :: RecordU l -> RecordU l -> RecordU l #

Read (UArray Int (GetElemTy l)) => Read (RecordU l) Source # 
Show (UArray Int (GetElemTy l)) => Show (RecordU l) Source # 

Methods

showsPrec :: Int -> RecordU l -> ShowS #

show :: RecordU l -> String #

showList :: [RecordU l] -> ShowS #

HMapUnboxF xs us => HMapUnboxF ((:) * (HList x) xs) ((:) * (RecordU x) us) Source # 
type LabelableTy RecordU Source # 

data 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.

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 Source #

works expected. See examples attached to bad.

Methods

hLookupByLabel :: Label l (RecordUS r) -> v -> v Source #

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

Methods

showsPrec :: Int -> RecordUS x -> ShowS #

show :: RecordUS x -> String #

showList :: [RecordUS x] -> ShowS #

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)])]

Minimal complete definition

sortForRecordUS

Instances

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

Methods

sortForRecordUS :: Record ((* ': x) xs) -> Record sorted Source #

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.

Minimal complete definition

hUpdateMany

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) Source #

implementation in terms of .<++.

Methods

hUpdateMany :: Record lv -> Record x -> Record x Source #

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

Methods

hUpdateMany :: Record lv -> RecordU r -> RecordU r Source #

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

hMap specialized to RecordU

internals for types

class HFindMany (ls :: [k]) (r :: [k]) (ns :: [HNat]) | ls r -> ns Source #

behaves like map HFind

Instances

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

class HNats2Integrals (ns :: [HNat]) where Source #

Minimal complete definition

hNats2Integrals

Methods

hNats2Integrals :: Integral i => Proxy ns -> [i] Source #

Instances

HNats2Integrals ([] HNat) Source # 

Methods

hNats2Integrals :: Integral i => Proxy [HNat] [HNat] -> [i] Source #

(HNats2Integrals ns, HNat2Integral n) => HNats2Integrals ((:) HNat n ns) Source # 

Methods

hNats2Integrals :: Integral i => Proxy [HNat] ((HNat ': n) ns) -> [i] Source #

class RecordUSCxt (x :: [*]) (u :: [*]) | x -> u, u -> x Source #

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

Instances

class HLookupByHNatUS (n :: HNat) (us :: [*]) (e :: *) | n us -> e Source #

Minimal complete definition

hLookupByHNatUS

Instances

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

Methods

hLookupByHNatUS :: Proxy HNat n -> HList ((* ': ru) us) -> e Source #

class HLookupByHNatUS1 (r :: Either HNat HNat) (n :: HNat) (u :: [*]) (us :: [*]) (e :: *) | r n u us -> e Source #

Minimal complete definition

hLookupByHNatUS1

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 Source # 

Methods

hLookupByHNatUS1 :: Proxy (Either HNat HNat) (Left HNat HNat t) -> Proxy HNat n -> RecordU u -> HList us -> le Source #

HLookupByHNatUS t us e => HLookupByHNatUS1 (Right HNat HNat t) n u us e Source # 

type family HSubtract (n1 :: HNat) (n2 :: HNat) :: Either HNat HNat Source #

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

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 ([] *) ([] *) Source # 
HMapUnboxF xs us => HMapUnboxF ((:) * (HList x) xs) ((:) * (RecordU x) us) Source # 

data UnboxF Source #

Instances

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

Methods

applyAB :: UnboxF -> hx -> ux Source #

data BoxF Source #

Instances

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

Methods

applyAB :: BoxF -> ux -> hx Source #

data EqTagValue Source #

Instances

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

type family GetElemTy (x :: [*]) :: * Source #

Instances

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

class ElemTyEq (xs :: [*]) Source #

all elements of the list have the same type

Instances

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

HList

A subset of Data.HList.HList is re-exported.

A subset of Data.HList.HSort

hSort :: HSort x y => HList x -> HList y Source #

type HSort x y = HSortBy HLeFn x y Source #

class (SameLength a b, HEqByFn le) => HSortBy le (a :: [*]) (b :: [*]) | le a -> b where Source #

quick sort with a special case for sorted lists

Minimal complete definition

hSortBy

Methods

hSortBy :: Proxy le -> HList a -> HList b Source #

Instances

(SameLength * * a b, HIsAscList k le a ok, HSortBy1 Bool k ok le a b, HEqByFn k le) => HSortBy k le a b Source # 

Methods

hSortBy :: Proxy le a -> HList b -> HList b Source #

data HLeFn Source #

the "standard" <= for types. Reuses HEqBy

Note that ghc-7.6 is missing instances for Symbol and Nat, so that sorting only works HNat (as used by Data.HList.Label3).

Instances

HEqByFn * HLeFn Source # 
(~) Bool ((<=?) x y) b => HEqBy * Nat HLeFn x y b Source #

only in ghc >= 7.7

(HEq Ordering (CmpSymbol x y) GT nb, (~) Bool (HNot nb) b) => HEqBy * Symbol HLeFn x y b Source #

only in ghc >= 7.7

>>> let b1 = Proxy :: HEqBy HLeFn "x" "y" b => Proxy b
>>> :t b1
b1 :: Proxy 'True
>>> let b2 = Proxy :: HEqBy HLeFn "x" "x" b => Proxy b
>>> :t b2
b2 :: Proxy 'True
>>> let b3 = Proxy :: HEqBy HLeFn "y" "x" b => Proxy b
>>> :t b3
b3 :: Proxy 'False
(~) Bool (HLe x y) b => HEqBy * HNat HLeFn x y b Source # 
HEqBy * k HLeFn x y b => HEqBy * * HLeFn (Proxy k x) (Proxy k y) b Source # 
HEqBy * k HLeFn x y b => HEqBy * * HLeFn (Label k x) (Label k y) b Source # 
HEqBy * k HLeFn x y b => HEqBy * * HLeFn (Tagged k x v) (Tagged k y w) b Source # 
(HEqBy * HNat HLeFn n m b, (~) * ns ns') => HEqBy * * HLeFn (Lbl n ns desc) (Lbl m ns' desc') b Source #

Data.HList.Label3 labels can only be compared if they belong to the same namespace.

data HDown a Source #

analogous to Down

Instances

HEqBy k2 k1 f y x b => HEqBy * k1 (HDown k2 f) x y b Source # 
HEqByFn k a => HEqByFn * (HDown k a) Source # 

class HSetBy (HNeq HLeFn) ps => HSet (ps :: [*]) Source #

Instances

HSetBy * (HNeq * HLeFn) ps => HSet ps Source # 

class HEqByFn lt => HSetBy lt (ps :: [*]) Source #

Provided the labels involved have an appropriate instance of HEqByFn, it would be possible to use the following definitions:

type HRLabelSet = HSet
type HLabelSet  = HSet

Instances

(HEqByFn k lt, HSortBy k lt ps ps', HAscList k lt ps') => HSetBy k lt ps Source # 

class HIsSet (ps :: [*]) (b :: Bool) | ps -> b Source #

>>> let xx = Proxy :: HIsSet [Label "x", Label "x"] b => Proxy b
>>> :t xx
xx :: Proxy 'False
>>> let xy = Proxy :: HIsSet [Label "x", Label "y"] b => Proxy b
>>> :t xy
xy :: Proxy 'True

Instances

HIsSetBy * (HNeq * HLeFn) ps b => HIsSet ps b Source # 

class HEqByFn lt => HIsSetBy lt (ps :: [*]) (b :: Bool) | lt ps -> b Source #

Instances

(HEqByFn k lt, HSortBy k lt ps ps', HIsAscList k lt ps' b) => HIsSetBy k lt ps b Source # 

class HEqByFn le => HAscList le (ps :: [*]) Source #

HAscList le xs confirms that xs is in ascending order, and reports which element is duplicated otherwise.

Instances

(HEqByFn k le, HAscList0 k le ps ps) => HAscList k le ps Source # 

class HEqByFn le => HIsAscList le (xs :: [*]) (b :: Bool) | le xs -> b Source #

HIsAscList le xs b is analogous to

b = all (\(x,y) -> x `le` y) (xs `zip` tail xs)

Instances

HEqByFn k le => HIsAscList k le ([] *) True Source # 
(HEqBy k * le x y b1, HIsAscList k le ((:) * y ys) b2, (~) Bool (HAnd b1 b2) b3) => HIsAscList k le ((:) * x ((:) * y ys)) b3 Source # 
HEqByFn k le => HIsAscList k le ((:) * x ([] *)) True Source # 

A subset of Data.HList.HCurry

class HLengthEq xs n => HCurry' (n :: HNat) f xs r | f xs -> r, r xs -> f, n f -> xs, xs -> n where Source #

'curry'/'uncurry' for many arguments and HLists instead of tuples

XXX the last FD xs -> n is needed to make hCompose infer the right types: arguably it shouldn't be needed

Minimal complete definition

hUncurry', hCurry'

Methods

hUncurry' :: Proxy n -> f -> HList xs -> r Source #

hCurry' :: Proxy n -> (HList xs -> r) -> f Source #

Instances

HCurry' HZero b ([] *) b Source # 

Methods

hUncurry' :: Proxy HNat HZero -> b -> HList [*] -> b Source #

hCurry' :: Proxy HNat HZero -> (HList [*] -> b) -> b Source #

HCurry' n b xs r => HCurry' (HSucc n) (x -> b) ((:) * x xs) r Source # 

Methods

hUncurry' :: Proxy HNat (HSucc n) -> (x -> b) -> HList ((* ': x) xs) -> r Source #

hCurry' :: Proxy HNat (HSucc n) -> (HList ((* ': x) xs) -> r) -> x -> b Source #

hCurry :: (ArityRev f n, ArityFwd f n, HCurry' n f xs r) => (HList xs -> r) -> f Source #

Note: with ghc-7.10 the Arity constraint added here does not work properly with hCompose, so it is possible that other uses of hCurry are better served by hCurry' Proxy.

hUncurry :: (ArityRev f n, ArityFwd f n, HCurry' n f xs r) => f -> HList xs -> r Source #

hCompose :: (HSplitAt1 ([] *) n2 xsys xs1 xs2, HCurry' n2 f1 xs1 x, HCurry' n1 b xs2 r, HCurry' n3 f2 xsys r, ArityFwd f1 n2, ArityFwd b n1, ArityRev f1 n2, ArityRev b n1, HAppendList1 * xs1 xs2 xsys) => (x -> b) -> f1 -> f2 Source #

compose two functions that take multiple arguments. The result of the second function is the first argument to the first function. An example is probably clearer:

>>> let f = hCompose (,,) (,)
>>> :t f
f :: ... -> ... -> ... -> ... -> ((..., ...), ..., ...)
>>> f 1 2 3 4
((1,2),3,4)

Note: polymorphism can make it confusing as to how many parameters a function actually takes. For example, the first two ids are id :: (a -> b) -> (a -> b) in

>>> (.) id id id 'y'
'y'
>>> hCompose id id id 'y'
'y'

still typechecks, but in that case hCompose i1 i2 i3 x == i1 ((i2 i3) x) has id with different types than @(.) i1 i2 i3 x == (i1 (i2 i3)) x

Prompted by http://stackoverflow.com/questions/28932054/can-hlistelim-be-composed-with-another-function

TIP

Public interface of Data.HList.TIP

data TIP (l :: [*]) Source #

TIPs are like Record, except element "i" of the list "l" has type Tagged e_i e_i

Instances

TypeIndexed Record TIP Source # 

Methods

typeIndexed :: (TypeIndexedCxt s t a b, Profunctor p, Functor f) => p (TIP (TagR a)) (f (TIP (TagR b))) -> p (Record s) (f (Record t)) Source #

(HUnzip TIP x y xy, HZipList xL yL xyL, (~) * lty (HList xL -> HList yL -> HList xyL), Coercible * lty (TIP x -> TIP y -> TIP xy), (~) [*] (UntagR x) xL, (~) [*] (UntagR y) yL, (~) [*] (UntagR xy) xyL, UntagTag x, UntagTag y, UntagTag xy) => HZip TIP x y xy Source # 

Methods

hZip :: TIP x -> TIP y -> TIP xy Source #

(HZipList xL yL xyL, (~) * lty (HList xyL -> (HList xL, HList yL)), Coercible * lty (TIP xy -> (TIP x, TIP y)), (~) [*] (UntagR x) xL, (~) [*] (TagR xL) x, (~) [*] (UntagR y) yL, (~) [*] (TagR yL) y, (~) [*] (UntagR xy) xyL, (~) [*] (TagR xyL) xy, SameLengths * ((:) [*] x ((:) [*] y ((:) [*] xy ([] [*])))), UntagTag x, UntagTag y, UntagTag xy) => HUnzip TIP x y xy Source # 

Methods

hUnzip :: TIP xy -> (TIP x, TIP y) Source #

(HDeleteAtLabel k Record e v v', HTypeIndexed v') => HDeleteAtLabel k TIP e v v' Source # 

Methods

hDeleteAtLabel :: Label TIP v -> e v' -> e v' Source #

(HUpdateAtLabel * Record e' e r r', HTypeIndexed r', (~) * e e') => HUpdateAtLabel * TIP e' e r r' Source # 

Methods

hUpdateAtLabel :: Label TIP e -> r -> e' r' -> e' r' Source #

LabelableTIPCxt k x s t a b => Labelable k x TIP s t a b Source #

make a Lens' (TIP s) a.

tipyLens provides a Lens (TIP s) (TIP t) a b, which tends to need too many type annotations to be practical

Associated Types

type LabelableTy (s :: [*] -> *) :: LabeledOpticType Source #

Methods

hLens' :: Label x TIP -> LabeledOptic x TIP s t a b b Source #

HasField * e (Record ((:) * x ((:) * y l))) e => HOccurs e (TIP ((:) * x ((:) * y l))) Source # 

Methods

hOccurs :: TIP ((* ': x) ((* ': y) l)) -> e Source #

(~) * tee (Tagged * e e) => HOccurs e (TIP ((:) * tee ([] *))) Source #

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.

Methods

hOccurs :: TIP ((* ': tee) [*]) -> e Source #

(HRLabelSet ((:) * (Tagged * e e) l), HTypeIndexed l) => HExtend e (TIP l) Source # 

Associated Types

type HExtendR e (TIP l) :: * Source #

Methods

(.*.) :: e -> TIP l -> HExtendR e (TIP l) Source #

Bounded (HList r) => Bounded (TIP r) Source # 

Methods

minBound :: TIP r #

maxBound :: TIP r #

Eq (HList a) => Eq (TIP a) Source # 

Methods

(==) :: TIP a -> TIP a -> Bool #

(/=) :: TIP a -> TIP a -> Bool #

Ord (HList r) => Ord (TIP r) Source # 

Methods

compare :: TIP r -> TIP r -> Ordering #

(<) :: TIP r -> TIP r -> Bool #

(<=) :: TIP r -> TIP r -> Bool #

(>) :: TIP r -> TIP r -> Bool #

(>=) :: TIP r -> TIP r -> Bool #

max :: TIP r -> TIP r -> TIP r #

min :: TIP r -> TIP r -> TIP r #

HMapOut (HComp HShow HUntag) l String => Show (TIP l) Source # 

Methods

showsPrec :: Int -> TIP l -> ShowS #

show :: TIP l -> String #

showList :: [TIP l] -> ShowS #

Ix (HList r) => Ix (TIP r) Source # 

Methods

range :: (TIP r, TIP r) -> [TIP r] #

index :: (TIP r, TIP r) -> TIP r -> Int #

unsafeIndex :: (TIP r, TIP r) -> TIP r -> Int

inRange :: (TIP r, TIP r) -> TIP r -> Bool #

rangeSize :: (TIP r, TIP r) -> Int #

unsafeRangeSize :: (TIP r, TIP r) -> Int

Semigroup (HList a) => Semigroup (TIP a) Source # 

Methods

(<>) :: TIP a -> TIP a -> TIP a #

sconcat :: NonEmpty (TIP a) -> TIP a #

stimes :: Integral b => b -> TIP a -> TIP a #

Monoid (HList a) => Monoid (TIP a) Source # 

Methods

mempty :: TIP a #

mappend :: TIP a -> TIP a -> TIP a #

mconcat :: [TIP a] -> TIP a #

((~) * e e', HasField * e (Record l) e') => HasField * e (TIP l) e' Source # 

Methods

hLookupByLabel :: Label e (TIP l) -> e' -> v Source #

(HAppend (HList l) (HList l'), HTypeIndexed (HAppendListR * l l')) => HAppend (TIP l) (TIP l') Source # 

Methods

hAppend :: TIP l -> TIP l' -> HAppendR * (TIP l) (TIP l') Source #

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

Subtyping for TIPs

type LabelableTy TIP Source # 
type HExtendR e (TIP l) Source # 
type HExtendR e (TIP l) = TIP ((:) * (Tagged * e e) l)
type HAppendR * (TIP l) (TIP l') Source # 
type HAppendR * (TIP l) (TIP l') = TIP (HAppendListR * l l')

tipyUpdate :: (SameLength' * * r r, HUpdateAtLabel * record v v r r) => v -> record r -> record r Source #

tipyLens :: (Functor f, HAppendList l1 ((:) * (Tagged * a2 a2) xs2), HAllTaggedLV (HAppendListR * l1 ((:) * (Tagged * a2 a2) xs2)), HLabelSet [*] (LabelsOf (HAppendListR * l1 ((:) * (Tagged * a2 a2) xs2))), HAllTaggedEq (HAppendListR * l1 ((:) * (Tagged * a2 a2) xs2)), HFind2 * b (Label * a1) (LabelsOf xs1) ((:) * (Label * x) (LabelsOf xs1)) n, HEq * (Label * a1) (Label * x) b, HLengthEq2 HNat l1 n, HLengthEq1 HNat l1 n, SameLength' * * (HReplicateR * n ()) l1, HAppendList1 * l1 ((:) * (Tagged * a1 a1) xs2) ((:) * (Tagged * x x) xs1), HSplitAt1 ([] *) n ((:) * (Tagged * x x) xs1) l1 ((:) * (Tagged * a1 a1) xs2)) => (a1 -> f a2) -> TIP ((:) * (Tagged * x x) xs1) -> f (TIP (HAppendListR * l1 ((:) * (Tagged * a2 a2) xs2))) Source #

provides a Lens (TIP s) (TIP t) a b

When using set (also known as .~), tipyLens' can address the ambiguity as to which field "a" should actually be updated.

tipyLens' :: (Functor f, SameLabels [*] [*] t t, SameLength' * * t t, HAllTaggedLV t, HLabelSet [*] (LabelsOf t), HAllTaggedEq t, HUpdateAtLabel2 * a a t t, HasField * a (Record t) a) => (a -> f a) -> TIP t -> f (TIP t) Source #

provides a Lens' (TIP s) a. hLens' :: Label a -> Lens' (TIP s) a is another option.

projection

tipyProject :: (H2ProjectByLabels ls t l b, HAllTaggedEq l, HLabelSet [*] (LabelsOf l), HAllTaggedLV l) => proxy ls -> TIP t -> TIP l Source #

Use Labels to specify the first argument

tipyProject2 :: (HAllTaggedLV l2, HAllTaggedLV l1, HLabelSet [*] (LabelsOf l2), HLabelSet [*] (LabelsOf l1), HAllTaggedEq l2, HAllTaggedEq l1, H2ProjectByLabels ls r l1 l2) => proxy ls -> TIP r -> (TIP l1, TIP l2) Source #

The same as tipyProject, except also return the types not requested in the proxy argument

tipyTuple :: (HDeleteAtLabel * r b v1 v2, HDeleteAtLabel * r b v3 v'2, HDeleteAtLabel * r a v2 v'1, HDeleteAtLabel * r a v1 v3, HOccurs b (r v1), HOccurs b (r v3), HOccurs a (r v2), HOccurs a (r v1)) => r v1 -> (a, b) Source #

project a TIP (or HList) into a tuple

tipyTuple' x = (hOccurs x, hOccurs x)

behaves similarly, except tipyTuple excludes the possibility of looking up the same element twice, which allows inferring a concrete type in more situations. For example

(\x y z -> tipyTuple (x .*. y .*. emptyTIP) `asTypeOf` (x, z)) () 'x'

has type Char -> ((), Char). tipyTuple' would need a type annotation to decide whether the type should be Char -> ((), Char) or () -> ((), ())

tipyTuple3 :: (HDeleteAtLabel * r b v1 v5, HDeleteAtLabel * r b v7 v'3, HDeleteAtLabel * r b v6 v4, HDeleteAtLabel * r c v5 v3, HDeleteAtLabel * r c v1 v2, HDeleteAtLabel * r c v4 v'2, HDeleteAtLabel * r a v3 v'1, HDeleteAtLabel * r a v2 v7, HDeleteAtLabel * r a v1 v6, HOccurs b (r v1), HOccurs b (r v7), HOccurs b (r v6), HOccurs c (r v5), HOccurs c (r v1), HOccurs c (r v4), HOccurs a (r v3), HOccurs a (r v2), HOccurs a (r v1)) => r v1 -> (a, b, c) Source #

tipyTuple4 :: (HDeleteAtLabel * r b v1 v10, HDeleteAtLabel * r b v13 v'4, HDeleteAtLabel * r b v12 v9, HDeleteAtLabel * r b v11 v8, HDeleteAtLabel * r c v10 v7, HDeleteAtLabel * r c v1 v6, HDeleteAtLabel * r c v9 v'3, HDeleteAtLabel * r c v8 v5, HDeleteAtLabel * r d v7 v4, HDeleteAtLabel * r d v6 v3, HDeleteAtLabel * r d v1 v2, HDeleteAtLabel * r d v5 v'2, HDeleteAtLabel * r a v4 v'1, HDeleteAtLabel * r a v3 v13, HDeleteAtLabel * r a v2 v12, HDeleteAtLabel * r a v1 v11, HOccurs b (r v1), HOccurs b (r v13), HOccurs b (r v12), HOccurs b (r v11), HOccurs c (r v10), HOccurs c (r v1), HOccurs c (r v9), HOccurs c (r v8), HOccurs d (r v7), HOccurs d (r v6), HOccurs d (r v1), HOccurs d (r v5), HOccurs a (r v4), HOccurs a (r v3), HOccurs a (r v2), HOccurs a (r v1)) => r v1 -> (a, b, c, d) Source #

tipyTuple5 :: (HDeleteAtLabel * r b v1 v17, HDeleteAtLabel * r b v21 v'5, HDeleteAtLabel * r b v20 v16, HDeleteAtLabel * r b v19 v15, HDeleteAtLabel * r b v18 v14, HDeleteAtLabel * r c v17 v13, HDeleteAtLabel * r c v1 v12, HDeleteAtLabel * r c v16 v'4, HDeleteAtLabel * r c v15 v11, HDeleteAtLabel * r c v14 v10, HDeleteAtLabel * r d v13 v9, HDeleteAtLabel * r d v12 v8, HDeleteAtLabel * r d v1 v7, HDeleteAtLabel * r d v11 v'3, HDeleteAtLabel * r d v10 v6, HDeleteAtLabel * r e v9 v5, HDeleteAtLabel * r e v8 v4, HDeleteAtLabel * r e v7 v3, HDeleteAtLabel * r e v1 v2, HDeleteAtLabel * r e v6 v'2, HDeleteAtLabel * r a v5 v'1, HDeleteAtLabel * r a v4 v21, HDeleteAtLabel * r a v3 v20, HDeleteAtLabel * r a v2 v19, HDeleteAtLabel * r a v1 v18, HOccurs b (r v1), HOccurs b (r v21), HOccurs b (r v20), HOccurs b (r v19), HOccurs b (r v18), HOccurs c (r v17), HOccurs c (r v1), HOccurs c (r v16), HOccurs c (r v15), HOccurs c (r v14), HOccurs d (r v13), HOccurs d (r v12), HOccurs d (r v1), HOccurs d (r v11), HOccurs d (r v10), HOccurs e (r v9), HOccurs e (r v8), HOccurs e (r v7), HOccurs e (r v1), HOccurs e (r v6), HOccurs a (r v5), HOccurs a (r v4), HOccurs a (r v3), HOccurs a (r v2), HOccurs a (r v1)) => r v1 -> (a, b, c, d, e) Source #

type TagUntag xs = TagUntagFD xs (TagR xs) Source #

class SameLength a ta => TagUntagFD a ta | a -> ta, ta -> a where Source #

TagR can also be used to avoid redundancy when defining types for TIC and TIP.

 type XShort = TagR [A,B,C,D]
 type XLong = [Tagged A A, Tagged B B, Tagged C C, Tagged D D]

an equivalent FD version, which is slightly better with respect to simplifying types containing type variables (in ghc-7.8 and 7.6): http://stackoverflow.com/questions/24110410/

With ghc-7.10 (http://ghc.haskell.org/trac/ghc/ticket/10009) the FD version is superior to the TF version:

class (UntagR (TagR a) ~ a) => TagUntag a where
    type TagR a :: [*]
    hTagSelf :: HList a -> HList (TagR a)
    hUntagSelf :: HList (TagR a) -> HList a

instance TagUntag '[] where
    type TagR '[] = '[]
    hTagSelf _ = HNil
    hUntagSelf _ = HNil

instance TagUntag xs => TagUntag (x ': xs) where
    type TagR (x ': xs) = Tagged x x ': TagR xs
    hTagSelf (HCons x xs) = Tagged x HCons hTagSelf xs
    hUntagSelf (HCons (Tagged x) xs) = x HCons hUntagSelf xs

type family UntagR (xs :: [*]) :: [*]
type instance UntagR '[] = '[]
type instance UntagR (x ': xs) = Untag1 x ': UntagR xs

Length information should flow backwards

>>> let len2 x = x `asTypeOf` (undefined :: HList '[a,b])
>>> let f = len2 $ hTagSelf (hReplicate Proxy ())
>>> :t f
f :: HList '[Tagged () (), Tagged () ()]

Minimal complete definition

hTagSelf, hUntagSelf

Methods

hTagSelf :: HList a -> HList ta Source #

hUntagSelf :: HList ta -> HList a Source #

Instances

TagUntagFD ([] *) ([] *) Source # 

Methods

hTagSelf :: HList [*] -> HList [*] Source #

hUntagSelf :: HList [*] -> HList [*] Source #

(TagUntagFD xs ys, (~) * txx (Tagged * x x)) => TagUntagFD ((:) * x xs) ((:) * txx ys) Source # 

Methods

hTagSelf :: HList ((* ': x) xs) -> HList ((* ': txx) ys) Source #

hUntagSelf :: HList ((* ': txx) ys) -> HList ((* ': x) xs) Source #

type family TagR (a :: [*]) :: [*] Source #

Instances

type TagR ([] *) Source # 
type TagR ([] *) = [] *
type TagR ((:) * x xs) Source # 
type TagR ((:) * x xs) = (:) * (Tagged * x x) (TagR xs)

TIP transform

class TransTIP op db where Source #

Transforming a TIP: applying to a TIP a (polyvariadic) function that takes arguments from a TIP and updates the TIP with the result.

In more detail: we have a typed-indexed collection TIP and we would like to apply a transformation function to it, whose argument types and the result type are all in the TIP. The function should locate its arguments based on their types, and update the TIP with the result. The function may have any number of arguments, including zero; the order of arguments should not matter.

The problem was posed by Andrew U. Frank on Haskell-Cafe, Sep 10, 2009. http://www.haskell.org/pipermail/haskell-cafe/2009-September/066217.html The problem is an interesting variation of the keyword argument problem.

Examples can be found in examples/TIPTransform.hs and examples/TIPTransformM.hs

Minimal complete definition

ttip

Methods

ttip :: op -> TIP db -> TIP db Source #

Instances

(HMember * (Tagged * op op) db b, Arity op n, TransTIP1 b n op db) => TransTIP op db Source # 

Methods

ttip :: op -> TIP db -> TIP db Source #

class Monad m => TransTIPM m op db where Source #

In March 2010, Andrew Frank extended the problem for monadic operations. This is the monadic version of TIPTransform.hs in the present directory.

This is the TF implementation. When specifying the operation to perform over a TIP, we can leave it polymorphic over the monad. The type checker will instantiate the monad based on the context.

Minimal complete definition

ttipM

Methods

ttipM :: op -> TIP db -> m (TIP db) Source #

Instances

(Monad m, HMember * (Tagged * op op) db b, Arity (m' op) n, TransTIPM1 b n m (m' op) db) => TransTIPM m (m' op) db Source # 

Methods

ttipM :: m' op -> TIP db -> m (TIP db) Source #

TIC

Public interface of Data.HList.TIC

data TIC (l :: [*]) Source #

A datatype for type-indexed co-products. A TIC is just a Variant, where the elements of the type-level list "l" are in the form Tagged x x.

Instances

TypeIndexed Variant TIC Source # 

Methods

typeIndexed :: (TypeIndexedCxt s t a b, Profunctor p, Functor f) => p (TIC (TagR a)) (f (TIC (TagR b))) -> p (Variant s) (f (Variant t)) Source #

HMapAux Variant f xs ys => HMapAux TIC f xs ys Source # 

Methods

hMapAux :: f -> TIC xs -> TIC ys Source #

(TICPrism s t a b, (~) * (Label k x) (Label * a), (~) * a b, (~) [*] s t, SameLength * * s t) => Labelable k x TIC s t a b Source #
hLens' :: Label a -> Prism' (TIC s) a

note that a more general function ticPrism :: Prism (TIC s) (TIC t) a b, cannot have an instance of Labelable

Note: `x :: k` according to the instance head, but the instance body forces the kind variable to be * later on. IE. (k ~ *)

Associated Types

type LabelableTy (s :: [*] -> *) :: LabeledOpticType Source #

Methods

hLens' :: Label x TIC -> LabeledOptic x TIC s t a b b Source #

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

Methods

hOccurs :: TIC l -> mo Source #

((~) * me (Maybe e), HOccursNot * (Tagged * e e) l) => HExtend me (TIC l) Source #
Nothing .*. x = x
Just a .*. y = mkTIC a

Associated Types

type HExtendR me (TIC l) :: * Source #

Methods

(.*.) :: me -> TIC l -> HExtendR me (TIC l) Source #

Bounded (Variant l) => Bounded (TIC l) Source # 

Methods

minBound :: TIC l #

maxBound :: TIC l #

Enum (Variant l) => Enum (TIC l) Source # 

Methods

succ :: TIC l -> TIC l #

pred :: TIC l -> TIC l #

toEnum :: Int -> TIC l #

fromEnum :: TIC l -> Int #

enumFrom :: TIC l -> [TIC l] #

enumFromThen :: TIC l -> TIC l -> [TIC l] #

enumFromTo :: TIC l -> TIC l -> [TIC l] #

enumFromThenTo :: TIC l -> TIC l -> TIC l -> [TIC l] #

Eq (Variant l) => Eq (TIC l) Source # 

Methods

(==) :: TIC l -> TIC l -> Bool #

(/=) :: TIC l -> TIC l -> Bool #

Ord (Variant l) => Ord (TIC l) Source # 

Methods

compare :: TIC l -> TIC l -> Ordering #

(<) :: TIC l -> TIC l -> Bool #

(<=) :: TIC l -> TIC l -> Bool #

(>) :: TIC l -> TIC l -> Bool #

(>=) :: TIC l -> TIC l -> Bool #

max :: TIC l -> TIC l -> TIC l #

min :: TIC l -> TIC l -> TIC l #

(ReadVariant l, HAllTaggedEq l, HRLabelSet l) => Read (TIC l) Source # 
ShowVariant l => Show (TIC l) Source #

TICs are not opaque

Methods

showsPrec :: Int -> TIC l -> ShowS #

show :: TIC l -> String #

showList :: [TIC l] -> ShowS #

Ix (Variant l) => Ix (TIC l) Source # 

Methods

range :: (TIC l, TIC l) -> [TIC l] #

index :: (TIC l, TIC l) -> TIC l -> Int #

unsafeIndex :: (TIC l, TIC l) -> TIC l -> Int

inRange :: (TIC l, TIC l) -> TIC l -> Bool #

rangeSize :: (TIC l, TIC l) -> Int #

unsafeRangeSize :: (TIC l, TIC l) -> Int

Semigroup (Variant l) => Semigroup (TIC l) Source # 

Methods

(<>) :: TIC l -> TIC l -> TIC l #

sconcat :: NonEmpty (TIC l) -> TIC l #

stimes :: Integral b => b -> TIC l -> TIC l #

Monoid (Variant l) => Monoid (TIC l) Source # 

Methods

mempty :: TIC l #

mappend :: TIC l -> TIC l -> TIC l #

mconcat :: [TIC l] -> TIC l #

HasField * o (Variant l) (Maybe o) => HasField * o (TIC l) (Maybe o) Source #

Public destructor (or, open union's projection function)

Methods

hLookupByLabel :: Label o (TIC l) -> Maybe o -> v Source #

type LabelableTy TIC Source # 
type HExtendR me (TIC l) Source # 
type HExtendR me (TIC l) = TIC ((:) * (Tagged * (UnMaybe me) (UnMaybe me)) l)

creating TIC

mkTIC :: (HAllTaggedEq l, HLabelSet [*] (LabelsOf l), HAllTaggedLV l, KnownNat (HNat2Nat n), HasField * i (Record l) i, HFind1 * i (UnLabel * i (LabelsOf l)) (UnLabel * i (LabelsOf l)) n) => i -> TIC l Source #

make a TIC for use in contexts where the result type is fixed

mkTIC1 :: forall i. MkVariant i i '[Tagged i i] => i -> TIC '[Tagged i i] Source #

make a TIC that contains one element

mkTIC' Source #

Arguments

:: (HTypeIndexed l, MkVariant i i l) 
=> i 
-> proxy l

the ordering of types in the l :: [*] matters. This argument is intended to fix the ordering it can be a Record, Variant, TIP, Proxy

-> TIC l 

Public constructor (or, open union's injection function)

get,set,modify

ticPrism :: (TICPrism s t a b, SameLength s t, Choice p, Applicative f) => (a `p` f b) -> TIC s `p` f (TIC t) Source #

ticPrism' :: forall s t a b. (HPrism a s t a b, a ~ b, s ~ t) => forall f p. (Applicative f, Choice p) => (a `p` f b) -> TIC s `p` f (TIC t) Source #

Prism' (TIC s) a

Variant

Public interface of Data.HList.Variant

data Variant (vs :: [*]) Source #

Variant vs has an implementation similar to Dynamic, except the contained value is one of the elements of the vs list, rather than being one particular instance of Typeable.

>>> v .!. _right
Nothing
>>> v .!. _left
Just 'x'

In some cases the pun quasiquote works with variants,

>>> let f [pun| left right |] = (left,right)
>>> f v
(Just 'x',Nothing)
>>> f w
(Nothing,Just 5)
>>> let add1 v = hMapV (Fun succ :: Fun '[Enum] '()) v
>>> f (add1 v)
(Just 'y',Nothing)
>>> f (add1 w)
(Nothing,Just 6)

Instances

Relabeled Variant Source # 

Methods

relabeled :: (HMapTaggedFn (RecordValuesR s) a, HMapTaggedFn (RecordValuesR b) t, SameLengths * (([*] ': s) (([*] ': a) (([*] ': t) (([*] ': b) [[*]])))), ([*] ~ RecordValuesR t) (RecordValuesR b), ([*] ~ RecordValuesR s) (RecordValuesR a), RecordValues b, RecordValues s, Profunctor p, Functor f) => p (Variant a) (f (Variant b)) -> p (Variant s) (f (Variant t)) Source #

TypeIndexed Variant TIC Source # 

Methods

typeIndexed :: (TypeIndexedCxt s t a b, Profunctor p, Functor f) => p (TIC (TagR a)) (f (TIC (TagR b))) -> p (Variant s) (f (Variant t)) Source #

(ExtendsVariant b t, ProjectVariant s a, ProjectExtendVariant s t, HLeftUnion b s bs, HRLabelSet bs, HRearrange (LabelsOf t) bs t) => Projected Variant s t a b Source #
Prism (Variant s) (Variant t) (Variant a) (Variant b)

Methods

projected :: ((LabeledOpticType ~ ty) (LabelableTy Variant), LabeledOpticP ty p, LabeledOpticF ty f) => p (Variant a) (f (Variant b)) -> p (Variant s) (f (Variant t)) Source #

HUpdateVariantAtLabelCxt k l e v v' n _e => HUpdateAtLabel k Variant l e v v' Source #
hUpdateAtLabel x e' (mkVariant x e proxy) == mkVariant x e' proxy
hUpdateAtLabel y e' (mkVariant x e proxy) == mkVariant x e  proxy

Methods

hUpdateAtLabel :: Label Variant e -> v -> l v' -> l r' Source #

(HPrism k x s t a b, (~) (* -> * -> *) to ((->) LiftedRep LiftedRep)) => Labelable k x Variant s t a b Source #

make a Prism (Variant s) (Variant t) a b

Associated Types

type LabelableTy (s :: [*] -> *) :: LabeledOpticType Source #

Methods

hLens' :: Label x Variant -> LabeledOptic x Variant s t a b b Source #

(HasField k x (Record vs) a, HFindLabel k x vs n, HNat2Integral n) => HasField k x (Variant vs) (Maybe a) Source # 

Methods

hLookupByLabel :: Label x (Variant vs) -> Maybe a -> v Source #

(ApplyAB f te te', HMapCxt Variant f ((:) * l ls) ((:) * l' ls')) => HMapAux Variant f ((:) * te ((:) * l ls)) ((:) * te' ((:) * l' ls')) Source # 

Methods

hMapAux :: f -> Variant ((* ': te) ((* ': l) ls)) -> Variant ((* ': te') ((* ': l') ls')) Source #

ApplyAB f te te' => HMapAux Variant f ((:) * te ([] *)) ((:) * te' ([] *)) Source # 

Methods

hMapAux :: f -> Variant ((* ': te) [*]) -> Variant ((* ': te') [*]) Source #

((~) * le (Tagged k l (Maybe e)), HOccursNot * (Label k l) (LabelsOf v)) => HExtend le (Variant v) Source #

Extension for Variants prefers the first value

(l .=. Nothing) .*. v = v
(l .=. Just e)  .*. _ = mkVariant l e Proxy

Associated Types

type HExtendR le (Variant v) :: * Source #

Methods

(.*.) :: le -> Variant v -> HExtendR le (Variant v) Source #

(HasField k l (Variant r) (Maybe u), HasFieldPath True ls u (Maybe v)) => HasFieldPath needJust ((:) * (Label k l) ls) (Variant r) (Maybe v) Source # 

Methods

hLookupByLabelPath1 :: Proxy Bool needJust -> Label [*] ((* ': Label k l) ls) -> Variant r -> Maybe v Source #

(Unvariant ((:) * txy ([] *)) txy, (~) * tx (Tagged k t x), (~) * ty (Tagged k t y), (~) * txy (Tagged k t (x, y))) => HUnzip Variant ((:) * tx ([] *)) ((:) * ty ([] *)) ((:) * txy ([] *)) Source # 

Methods

hUnzip :: Variant ((* ': txy) [*]) -> (Variant ((* ': tx) [*]), Variant ((* ': ty) [*])) Source #

(HUnzip Variant ((:) * x2 xs) ((:) * y2 ys) ((:) * xy2 xys), SameLength * * xs ys, SameLength * * ys 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)) Source # 

Methods

hUnzip :: Variant ((* ': txy) ((* ': xy2) xys)) -> (Variant ((* ': tx) ((* ': x2) xs)), Variant ((* ': ty) ((* ': y2) ys))) Source #

(Bounded x, Bounded z, (~) [*] (HRevAppR * ((:) * (Tagged k2 s x) xs) ([] *)) ((:) * (Tagged k1 t z) sx), MkVariant k1 t z ((:) * (Tagged k2 s x) xs)) => Bounded (Variant ((:) * (Tagged k2 s x) xs)) Source # 

Methods

minBound :: Variant ((* ': Tagged k2 s x) xs) #

maxBound :: Variant ((* ': Tagged k2 s x) xs) #

Enum x => Enum (Variant ((:) * (Tagged k s x) ([] *))) Source #

While the instances could be written Enum (Variant '[]) Eq/Ord which cannot produce values, so they have instances for empty variants (unsafeEmptyVariant). Enum can produce values, so it is better that fromEnum 0 :: Variant '[] fails with No instance for Enum (Variant '[]) than producing an invalid variant.

Methods

succ :: Variant ((* ': Tagged k s x) [*]) -> Variant ((* ': Tagged k s x) [*]) #

pred :: Variant ((* ': Tagged k s x) [*]) -> Variant ((* ': Tagged k s x) [*]) #

toEnum :: Int -> Variant ((* ': Tagged k s x) [*]) #

fromEnum :: Variant ((* ': Tagged k s x) [*]) -> Int #

enumFrom :: Variant ((* ': Tagged k s x) [*]) -> [Variant ((* ': Tagged k s x) [*])] #

enumFromThen :: Variant ((* ': Tagged k s x) [*]) -> Variant ((* ': Tagged k s x) [*]) -> [Variant ((* ': Tagged k s x) [*])] #

enumFromTo :: Variant ((* ': Tagged k s x) [*]) -> Variant ((* ': Tagged k s x) [*]) -> [Variant ((* ': Tagged k s x) [*])] #

enumFromThenTo :: Variant ((* ': Tagged k s x) [*]) -> Variant ((* ': Tagged k s x) [*]) -> Variant ((* ': Tagged k s x) [*]) -> [Variant ((* ': Tagged k s x) [*])] #

(Enum x, Bounded x, Enum (Variant ((:) * y z))) => Enum (Variant ((:) * (Tagged k s x) ((:) * y z))) Source #
>>> let t = minBound :: Variant '[Tagged "x" Bool, Tagged "y" Bool]
>>> [t .. maxBound]
[V{x=False},V{x=True},V{y=False},V{y=True}]
Odd behavior
There are some arguments that this instance should not exist.

The last type in the Variant does not need to be Bounded. This means that enumFrom behaves a bit unexpectedly:

>>> [False .. ]
[False,True]
>>> [t .. ]
[V{x=False},V{x=True},V{y=False},V{y=True},V{y=*** Exception: Prelude.Enum.Bool.toEnum: bad argument

This is a "feature" because it allows an Enum (Variant '[Tagged "a" Bool, Tagged "n" Integer])

Another difficult choice is that the lower bound is fromEnum 0 rather than minBound:

>>> take 5 [ minBound :: Variant '[Tagged "b" Bool, Tagged "i" Int] .. ]
[V{b=False},V{b=True},V{i=0},V{i=1},V{i=2}]

Methods

succ :: Variant ((* ': Tagged k s x) ((* ': y) z)) -> Variant ((* ': Tagged k s x) ((* ': y) z)) #

pred :: Variant ((* ': Tagged k s x) ((* ': y) z)) -> Variant ((* ': Tagged k s x) ((* ': y) z)) #

toEnum :: Int -> Variant ((* ': Tagged k s x) ((* ': y) z)) #

fromEnum :: Variant ((* ': Tagged k s x) ((* ': y) z)) -> Int #

enumFrom :: Variant ((* ': Tagged k s x) ((* ': y) z)) -> [Variant ((* ': Tagged k s x) ((* ': y) z))] #

enumFromThen :: Variant ((* ': Tagged k s x) ((* ': y) z)) -> Variant ((* ': Tagged k s x) ((* ': y) z)) -> [Variant ((* ': Tagged k s x) ((* ': y) z))] #

enumFromTo :: Variant ((* ': Tagged k s x) ((* ': y) z)) -> Variant ((* ': Tagged k s x) ((* ': y) z)) -> [Variant ((* ': Tagged k s x) ((* ': y) z))] #

enumFromThenTo :: Variant ((* ': Tagged k s x) ((* ': y) z)) -> Variant ((* ': Tagged k s x) ((* ': y) z)) -> Variant ((* ': Tagged k s x) ((* ': y) z)) -> [Variant ((* ': Tagged k s x) ((* ': y) z))] #

(Eq (Variant xs), Eq x) => Eq (Variant ((:) * x xs)) Source # 

Methods

(==) :: Variant ((* ': x) xs) -> Variant ((* ': x) xs) -> Bool #

(/=) :: Variant ((* ': x) xs) -> Variant ((* ': x) xs) -> Bool #

Eq (Variant ([] *)) Source # 

Methods

(==) :: Variant [*] -> Variant [*] -> Bool #

(/=) :: Variant [*] -> Variant [*] -> Bool #

(Typeable * (Variant v), GfoldlVariant v v, GunfoldVariant v v, VariantConstrs v) => Data (Variant v) Source # 

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Variant v -> c (Variant v) #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Variant v) #

toConstr :: Variant v -> Constr #

dataTypeOf :: Variant v -> DataType #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c (Variant v)) #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Variant v)) #

gmapT :: (forall b. Data b => b -> b) -> Variant v -> Variant v #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Variant v -> r #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Variant v -> r #

gmapQ :: (forall d. Data d => d -> u) -> Variant v -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> Variant v -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Variant v -> m (Variant v) #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Variant v -> m (Variant v) #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Variant v -> m (Variant v) #

(Ord x, Ord (Variant xs)) => Ord (Variant ((:) * x xs)) Source # 

Methods

compare :: Variant ((* ': x) xs) -> Variant ((* ': x) xs) -> Ordering #

(<) :: Variant ((* ': x) xs) -> Variant ((* ': x) xs) -> Bool #

(<=) :: Variant ((* ': x) xs) -> Variant ((* ': x) xs) -> Bool #

(>) :: Variant ((* ': x) xs) -> Variant ((* ': x) xs) -> Bool #

(>=) :: Variant ((* ': x) xs) -> Variant ((* ': x) xs) -> Bool #

max :: Variant ((* ': x) xs) -> Variant ((* ': x) xs) -> Variant ((* ': x) xs) #

min :: Variant ((* ': x) xs) -> Variant ((* ': x) xs) -> Variant ((* ': x) xs) #

Ord (Variant ([] *)) Source # 

Methods

compare :: Variant [*] -> Variant [*] -> Ordering #

(<) :: Variant [*] -> Variant [*] -> Bool #

(<=) :: Variant [*] -> Variant [*] -> Bool #

(>) :: Variant [*] -> Variant [*] -> Bool #

(>=) :: Variant [*] -> Variant [*] -> Bool #

max :: Variant [*] -> Variant [*] -> Variant [*] #

min :: Variant [*] -> Variant [*] -> Variant [*] #

ReadVariant v => Read (Variant v) Source #

A corresponding read instance

ShowVariant vs => Show (Variant vs) Source #

Variants are not opaque

Methods

showsPrec :: Int -> Variant vs -> ShowS #

show :: Variant vs -> String #

showList :: [Variant vs] -> ShowS #

(Semigroup x, Semigroup (Variant ((:) * a b))) => Semigroup (Variant ((:) * (Tagged k t x) ((:) * a b))) Source # 

Methods

(<>) :: Variant ((* ': Tagged k t x) ((* ': a) b)) -> Variant ((* ': Tagged k t x) ((* ': a) b)) -> Variant ((* ': Tagged k t x) ((* ': a) b)) #

sconcat :: NonEmpty (Variant ((* ': Tagged k t x) ((* ': a) b))) -> Variant ((* ': Tagged k t x) ((* ': a) b)) #

stimes :: Integral b => b -> Variant ((* ': Tagged k t x) ((* ': a) b)) -> Variant ((* ': Tagged k t x) ((* ': a) b)) #

(Unvariant ((:) * (Tagged k t x) ([] *)) x, Semigroup x) => Semigroup (Variant ((:) * (Tagged k t x) ([] *))) Source # 

Methods

(<>) :: Variant ((* ': Tagged k t x) [*]) -> Variant ((* ': Tagged k t x) [*]) -> Variant ((* ': Tagged k t x) [*]) #

sconcat :: NonEmpty (Variant ((* ': Tagged k t x) [*])) -> Variant ((* ': Tagged k t x) [*]) #

stimes :: Integral b => b -> Variant ((* ': Tagged k t x) [*]) -> Variant ((* ': Tagged k t x) [*]) #

(Monoid x, Monoid (Variant ((:) * a b))) => Monoid (Variant ((:) * (Tagged k t x) ((:) * a b))) Source # 

Methods

mempty :: Variant ((* ': Tagged k t x) ((* ': a) b)) #

mappend :: Variant ((* ': Tagged k t x) ((* ': a) b)) -> Variant ((* ': Tagged k t x) ((* ': a) b)) -> Variant ((* ': Tagged k t x) ((* ': a) b)) #

mconcat :: [Variant ((* ': Tagged k t x) ((* ': a) b))] -> Variant ((* ': Tagged k t x) ((* ': a) b)) #

(Unvariant ((:) * (Tagged k t x) ([] *)) x, Monoid x) => Monoid (Variant ((:) * (Tagged k t x) ([] *))) Source # 

Methods

mempty :: Variant ((* ': Tagged k t x) [*]) #

mappend :: Variant ((* ': Tagged k t x) [*]) -> Variant ((* ': Tagged k t x) [*]) -> Variant ((* ': Tagged k t x) [*]) #

mconcat :: [Variant ((* ': Tagged k t x) [*])] -> Variant ((* ': Tagged k t x) [*]) #

(SameLength * * s a, ExtendsVariant s a, SameLength * * b t, ExtendsVariant b t) => Rearranged [*] Variant s t a b Source # 

Methods

rearranged :: (Profunctor p, Functor f) => p (s b) (f (s b)) -> p (s t) (f (s a)) Source #

type LabelableTy Variant Source # 
type HExtendR le (Variant v) Source # 
type HExtendR le (Variant v) = Variant ((:) * (UnMaybe le) v)

mkVariant Source #

Arguments

:: MkVariant x v vs 
=> Label x

the tag

-> v

value to be stored

-> proxy vs

a helper to fix the ordering and types of the potential values that this variant contains. Typically this will be a Proxy, Record or another Variant

-> Variant vs 

mkVariant1 :: Label k l -> e -> Variant ((:) * (Tagged k l e) ([] *)) Source #

castVariant :: (RecordValuesR v ~ RecordValuesR v', SameLength v v') => Variant v -> Variant v' Source #

in ghc>=7.8, coerce is probably a better choice

newtype HMapV f Source #

Apply a function to all possible elements of the variant

Constructors

HMapV f 

Instances

((~) * vx (Variant x), (~) * vy (Variant y), HMapAux Variant (HFmap f) x y, SameLength * * x y) => ApplyAB (HMapV f) vx vy Source #

apply a function to all values that could be in the variant.

Methods

applyAB :: HMapV f -> vx -> vy Source #

hMapV :: (SameLength' * * y x, SameLength' * * x y, HMapAux Variant (HFmap f) x y) => f -> Variant x -> Variant y Source #

shortcut for applyAB . HMapV. hMap is more general

hMapOutV :: forall x y z f. (SameLength x y, HMapAux Variant (HFmap f) x y, Unvariant y z, HMapOutV_gety x z ~ y) => f -> Variant x -> z Source #

hMapOutV f = unvariant . hMapV f, except an ambiguous type variable is resolved by HMapOutV_gety

class ZipVariant x y xy | x y -> xy, xy -> x y where Source #

Applies to variants that have the same labels in the same order. A generalization of

zipEither :: Either a b -> Either a b -> Maybe (Either (a,a) (b,b))
zipEither (Left a) (Left a') = Just (Left (a,a'))
zipEither (Right a) (Right a') = Just (Right (a,a'))
zipEither _ _ = Nothing

see HZip for zipping other collections

Minimal complete definition

zipVariant

Methods

zipVariant :: Variant x -> Variant y -> Maybe (Variant xy) Source #

Instances

ZipVariant ([] *) ([] *) ([] *) Source # 

Methods

zipVariant :: Variant [*] -> Variant [*] -> Maybe (Variant [*]) Source #

((~) * tx (Tagged k t x), (~) * ty (Tagged k t y), (~) * txy (Tagged k t (x, y)), ZipVariant xs ys zs, MkVariant k t (x, y) ((:) * txy zs)) => ZipVariant ((:) * tx xs) ((:) * ty ys) ((:) * txy zs) Source # 

Methods

zipVariant :: Variant ((* ': tx) xs) -> Variant ((* ': ty) ys) -> Maybe (Variant ((* ': txy) zs)) Source #

class (SameLength v v', SameLabels v v') => ZipVR fs v v' | fs v -> v' where Source #

Apply a record of functions to a variant of values. The functions are selected based on those having the same label as the value.

Minimal complete definition

zipVR_

Methods

zipVR_ :: Record fs -> Variant v -> Variant v' Source #

zipVR is probably a better choice in most situations, since it requires that fs has one function for every element of v

Instances

ZipVR fs ([] *) ([] *) Source # 

Methods

zipVR_ :: Record fs -> Variant [*] -> Variant [*] Source #

((~) * lv (Tagged k l v), (~) * lv' (Tagged k l v'), HMemberM * (Label k l) (LabelsOf fs) b, HasFieldM k l (Record fs) f, (~) * (DemoteMaybe (v -> v) f) (v -> v'), MkVariant k l v' ((:) * lv' rs), ZipVR fs vs rs) => ZipVR fs ((:) * lv vs) ((:) * lv' rs) Source # 

Methods

zipVR_ :: Record fs -> Variant ((* ': lv) vs) -> Variant ((* ': lv') rs) Source #

zipVR :: (SameLabels fs v, SameLength fs v, ZipVR fs v v', ZipVRCxt fs v v') => Record fs -> Variant v -> Variant v' Source #

>>> let xy = x .*. y .*. emptyProxy
>>> let p = Proxy `asLabelsOf` xy
>>> let vs = [ mkVariant x 1.0 p, mkVariant y () p ]
>>> zipVR (hBuild (+1) id) `map` vs
[V{x=2.0},V{y=()}]

projection

many

class (ProjectVariant x yin, ProjectVariant x yout) => SplitVariant x yin yout where Source #

Minimal complete definition

splitVariant

Methods

splitVariant :: Variant x -> Either (Variant yin) (Variant yout) Source #

Instances

(ProjectVariant x yin, ProjectVariant x yout, H2ProjectByLabels (LabelsOf yin) x xi xo, HRearrange (LabelsOf yin) xi yin, HRearrange (LabelsOf yout) xo yout, HLeftUnion xi xo xixo, HRearrange (LabelsOf x) xixo x, HAllTaggedLV x, HAllTaggedLV yin, HAllTaggedLV yout) => SplitVariant x yin yout Source # 

Methods

splitVariant :: Variant x -> Either (Variant yin) (Variant yout) Source #

class ProjectVariant x y where Source #

convert a variant with more fields into one with fewer (or the same) fields.

>>> let ty = Proxy :: Proxy [Tagged "left" Int, Tagged "right" Int]
>>> let l = mkVariant _left 1 ty
>>> let r = mkVariant _right 2 ty
>>> map projectVariant [l, r] :: [Maybe (Variant '[Tagged "left" Int])]
[Just V{left=1},Nothing]

rearrangeVariant = fromJust . projectVariant is one implementation of rearrangeVariant, since the result can have the same fields with a different order:

>>> let yt = Proxy :: Proxy [Tagged "right" Int, Tagged "left" Int]
>>> map projectVariant [l, r] `asTypeOf` [Just (mkVariant _left 0 yt)]
[Just V{left=1},Just V{right=2}]

Minimal complete definition

projectVariant

Instances

ProjectVariant x ([] *) Source # 
(ProjectVariant x ys, HasField k t (Variant x) (Maybe y), HOccursNot * (Label k t) (LabelsOf ys), (~) * ty (Tagged k t y)) => ProjectVariant x ((:) * ty ys) Source # 

Methods

projectVariant :: Variant x -> Maybe (Variant ((* ': ty) ys)) Source #

class (HAllTaggedLV y, HAllTaggedLV x) => ExtendsVariant x y where Source #

projectVariant . extendsVariant = Just (when the types match up)

extendVariant is a special case

Minimal complete definition

extendsVariant

Instances

(MkVariant k l e y, (~) * le (Tagged k l e), ExtendsVariant ((:) * b bs) y) => ExtendsVariant ((:) * le ((:) * b bs)) y Source # 

Methods

extendsVariant :: Variant ((* ': le) ((* ': b) bs)) -> Variant y Source #

(HAllTaggedLV x, Unvariant ((:) * le ([] *)) e, MkVariant k l e x, (~) * le (Tagged k l e)) => ExtendsVariant ((:) * le ([] *)) x Source # 

Methods

extendsVariant :: Variant ((* ': le) [*]) -> Variant x Source #

class HAllTaggedLV y => ProjectExtendVariant x y where Source #

projectExtendVariant = fmap extendVariant . projectVariant

where intermediate variant is as large as possible. Used to implement Data.HList.Labelable.projected

Note that:

>>> let r = projectExtendVariant (mkVariant1 Label 1 :: Variant '[Tagged "x" Int])
>>> r :: Maybe (Variant '[Tagged "x" Integer])
Nothing

Minimal complete definition

projectExtendVariant

Instances

HAllTaggedLV y => ProjectExtendVariant ([] *) y Source # 
((~) * lv (Tagged k l v), HMemberM * lv y inY, ProjectExtendVariant' inY lv y, ProjectExtendVariant xs y) => ProjectExtendVariant ((:) * lv xs) y Source # 

Methods

projectExtendVariant :: Variant ((* ': lv) xs) -> Maybe (Variant y) Source #

one

class (SameLength s t, SameLabels s t) => HPrism x s t a b | x s -> a, x t -> b, x s b -> t, x t a -> s where Source #

Make a Prism (Variant s) (Variant t) a b out of a Label.

See Data.HList.Labelable.hLens' is a more overloaded version.

Few type annotations are necessary because of the restriction that s and t have the same labels in the same order, and to get "t" the "a" in "s" is replaced with "b".

Minimal complete definition

hPrism

Methods

hPrism :: (Choice p, Applicative f) => Label x -> p a (f b) -> p (Variant s) (f (Variant t)) Source #

Instances

(MkVariant k x b t, HasField k x (Variant s) (Maybe a), SameLength * * s t, SameLabels [*] [*] s t, H2ProjectByLabels ((:) * (Label k x) ([] *)) s si so, H2ProjectByLabels ((:) * (Label k x) ([] *)) t ti to, (~) [*] so to, HUpdateAtLabel k Variant x b s t, HUpdateAtLabel k Variant x a t s) => HPrism k x s t a b Source # 

Methods

hPrism :: (Choice p, Applicative f) => Label x s -> p b (f b) -> p (Variant t) (f (Variant a)) Source #

unvarianted :: (Unvariant' s a, Unvariant' t b, SameLabels s t, SameLength s t, Functor f) => (a -> f b) -> Variant s -> f (Variant t) Source #

Lens (Variant s) (Variant t) a b

Analogue of Control.Lens.chosen :: Lens (Either a a) (Either b b) a b

unvarianted' :: (Functor f, SameLength' * * t t, SameLabels [*] [*] t t, HAllEqVal ((:) * (Tagged * () a) t) b, HAllEqVal t b, HAllEqVal' ((:) * (Tagged * () a) t), Unvariant1 Bool b t a) => (a -> f a) -> Variant t -> f (Variant t) Source #

Lens' (Variant s) a

where we might have s ~ '[Tagged t1 a, Tagged t2 a]

splitVariant1 :: Variant (Tagged s x ': xs) -> Either x (Variant xs) Source #

splitVariant1' :: Variant (x ': xs) -> Either x (Variant xs) Source #

x ~ Tagged s t

implementation

class Unvariant v e | v -> e where Source #

Convert a Variant which has all possibilities having the same type into a value of that type. Analogous to either id id.

See also unvariant'

Minimal complete definition

unvariant

Methods

unvariant :: Variant v -> e Source #

Instances

(Unvariant1 Bool b v e, HAllEqVal v b, HAllEqVal ((:) * (Tagged * () e) v) b) => Unvariant v e Source # 

Methods

unvariant :: Variant v -> e Source #

class Unvariant' v e | v -> e where Source #

Similar to unvariant, except type variables in v will be made equal to e if possible. That allows the type of Nothing to be inferred as Maybe Char.

>>> unvariant' $ x .=. Nothing .*. mkVariant1 y 'y'
'y'

However, this difference leads to more local error messages (Couldn't match type ‘()’ with ‘Char’), rather than the following with unvariant:

Fail
   '("Variant",
     '[Tagged "left" Char, Tagged "right" ()],
     "must have all values equal to ",
     e))

Minimal complete definition

unvariant'

Methods

unvariant' :: Variant v -> e Source #

Instances

(HAllEqVal' ((:) * (Tagged * () e) v), Unvariant v e) => Unvariant' v e Source # 

Methods

unvariant' :: Variant v -> e Source #

Conversions between collections

class TypeIndexed r tr | r -> tr, tr -> r where Source #

Conversion between type indexed collections (TIC and TIP) and the corresponding collection that has other label types (Variant and Record respectively)

See typeIndexed'

Minimal complete definition

typeIndexed

Methods

typeIndexed :: forall p f s t a b. (TypeIndexedCxt s t a b, Profunctor p, Functor f) => p (tr (TagR a)) (f (tr (TagR b))) -> p (r s) (f (r t)) Source #

Iso (r s) (r t) (tr a) (tr b)

Instances

TypeIndexed Record TIP Source # 

Methods

typeIndexed :: (TypeIndexedCxt s t a b, Profunctor p, Functor f) => p (TIP (TagR a)) (f (TIP (TagR b))) -> p (Record s) (f (Record t)) Source #

TypeIndexed Variant TIC Source # 

Methods

typeIndexed :: (TypeIndexedCxt s t a b, Profunctor p, Functor f) => p (TIC (TagR a)) (f (TIC (TagR b))) -> p (Variant s) (f (Variant t)) Source #

typeIndexed' :: ((~#) [*] [*] (RecordValuesR (TagR b)) b, Functor f, Profunctor p, TagUntagFD b (TagR b), HLabelSet [*] (LabelsOf (TagR b)), HAllTaggedLV (TagR b), SameLength' * * b b, SameLength' * * (TagR b) (TagR b), SameLabels [*] [*] (TagR b) (TagR b), RecordValues (TagR b), HMapAux HList TaggedFn b (TagR b), TypeIndexed r tr) => p (tr (TagR b)) (f (tr (TagR b))) -> p (r (TagR b)) (f (r (TagR b))) Source #

Iso' (Variant s) (TIC a)
Iso' (Record s) (TIP a)

where s has a type like '[Tagged "x" Int], and a has a type like '[Tagged Int Int].

HList and Record

HList and TIP

tipHList :: (TagUntagFD a2 l, TagUntagFD a1 ta, Functor f, Profunctor p) => p (HList a1) (f (HList a2)) -> p (TIP ta) (f (TIP l)) Source #

Iso (TIP (TagR a)) (TIP (TagR b)) (HList a) (HList b)

tipHList' :: (Profunctor p, Functor f, TagUntagFD a l) => p (HList a) (f (HList a)) -> p (TIP l) (f (TIP l)) Source #

Iso' (TIP (TagR s)) (HList a)

Record and 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' :: (HMapAux HList TaggedFn (RecordValuesR y) y, SameLength' * * (HReplicateR * n ()) y, IArray UArray (GetElemTy y), HLengthEq2 HNat y n, HLengthEq1 HNat y n, KnownNat (HNat2Nat n), HList2List (RecordValuesR y) (GetElemTy y), RecordValues y, Functor f, Profunctor p) => p (RecordU y) (f (RecordU y)) -> p (Record y) (f (Record y)) Source #

Iso' (Record x) (RecordU x)

Record and RecordUS

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

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

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

Iso' (Record x) (RecordUS x)

Record and Variant

hMaybied :: (Applicative f, Choice p, SameLength' * * x r, SameLength' * * r x, HMapAux HList (HFmap HCastF) x r, VariantToHMaybied v1 x, VariantToHMaybied v2 r, HFoldr HMaybiedToVariantFs [Variant ([] *)] x [Variant v1]) => p (Variant v1) (f (Variant v2)) -> p (Record x) (f (Record r)) Source #

Prism (Record tma) (Record tmb) (Variant ta) (Variant tb)

see hMaybied'

hMaybied' :: (HFoldr HMaybiedToVariantFs [Variant ([] *)] x [Variant v], VariantToHMaybied v x, HMapAux HList (HFmap HCastF) x x, SameLength' * * x x, Choice p, Applicative f) => p (Variant v) (f (Variant v)) -> p (Record x) (f (Record x)) Source #

Prism' (Record tma) (Variant ta)

where tma and tmb are lists like

tma ~ '[Tagged x (Maybe a), Tagged y (Maybe b)]
ta  ~ '[Tagged x        a , Tagged y        b ]

If one element of the record is Just, the Variant will contain that element. Otherwise, the prism fails.

Note

The types work out to define a prism:

l = prism' variantToHMaybied (listToMaybe . hMaybiedToVariants)

but the law: s^?l ≡ Just a ==> l # a ≡ s is not followed, because we could have:

  s, s2 :: Record '[Tagged "x" (Maybe Int), Tagged "y" (Maybe Char)]
  s = hBuild (Just 1) (Just '2')
  s2 = hBuild (Just 1) Nothing

  v :: Variant '[Tagged "x" Int, Tagged "y" Char]
  v = mkVariant (Label :: Label "x") 1 Proxy

So that s^?l == Just v. But l#v == s2 /= s, while the law requires l#v == s. hMaybied avoids this problem by only producing a value when there is only one present.

Newtype wrappers

ticVariant :: (Functor f, Profunctor p) => p (Variant l1) (f (Variant l2)) -> p (TIC l1) (f (TIC l2)) Source #

Iso (TIC s) (TIC t) (Variant s) (Variant t)

typeIndexed may be more appropriate

ticVariant' :: (Profunctor p, Functor f) => p (Variant l) (f (Variant l)) -> p (TIC l) (f (TIC l)) Source #

Iso' (TIC s) (Variant s)

tipRecord :: (Functor f, Profunctor p) => p (Record r) (f (Record l)) -> p (TIP r) (f (TIP l)) Source #

Iso (TIP s) (TIP t) (Record s) (Record t)

typeIndexed may be more appropriate

tipRecord' :: (Profunctor p, Functor f) => p (Record l) (f (Record l)) -> p (TIP l) (f (TIP l)) Source #

Iso' (TIP (TagR s)) (Record a)

implementation

class VariantToHMaybied v r | v -> r, r -> v where Source #

Minimal complete definition

variantToHMaybied

Instances

VariantToHMaybied ([] *) ([] *) Source # 
(VariantToHMaybied v r, HReplicateF nr ConstTaggedNothing () r, (~) * tx (Tagged k t x), (~) * tmx (Tagged k t (Maybe x))) => VariantToHMaybied ((:) * tx v) ((:) * tmx r) Source # 

Methods

variantToHMaybied :: Variant ((* ': tx) v) -> Record ((* ': tmx) r) Source #

data HMaybiedToVariantFs Source #

Instances

((~) * x (Tagged k t (Maybe e), [Variant v]), (~) * y [Variant ((:) * (Tagged k t e) v)], MkVariant k t e ((:) * (Tagged k t e) v)) => ApplyAB HMaybiedToVariantFs x y Source # 

Methods

applyAB :: HMaybiedToVariantFs -> x -> y Source #

hMaybiedToVariants :: (HFoldr HMaybiedToVariantFs [Variant '[]] r [Variant v], VariantToHMaybied v r) => Record r -> [Variant v] Source #

Every element of the record that is Just becomes one element in the resulting list. See hMaybied' example types that r and v can take.

Data.HList.Keyword

the "public" parts. More examples are in the module documentation.

class Kw (fn :: *) (arg_def :: [*]) r where Source #

kw takes a HList whose first element is a function, and the rest of the elements are default values. A useful trick is to have a final argument () which is not eaten up by a label (A only takes 1 argument). That way when you supply the () it knows there are no more arguments (?).

>>> data A = A
>>> instance IsKeyFN (A -> a -> b) True
>>> let f A a () = a + 1
>>> let f' = f .*. A .*. 1 .*. HNil
>>> kw f' A 0 ()
1
>>> kw f' ()
2

Minimal complete definition

kw

Methods

kw :: HList (fn ': arg_def) -> r Source #

Instances

(KW' Bool rflag fn akws arg_def r, (~) * akws (Arg [*] kws ([] *)), ReflectFK' * [*] flag fn kws, IsKeyFN r rflag, IsKeyFN fn flag) => Kw fn arg_def r Source # 

Methods

kw :: HList ((* ': fn) arg_def) -> r Source #

recToKW :: forall a b. (HMapCxt HList TaggedToKW a b, HConcat b) => Record a -> HList (HConcatR b) Source #

convert a Record into a list that can supply default arguments for kw

A bit of setup:

>>> :set -XQuasiQuotes
>>> import Data.HList.RecordPuns
>>> let f (_ :: Label "a") a (_ :: Label "b") b () = a `div` b
>>> let a = 2; b = 1; f' = f .*. recToKW [pun| a b |]
>>> kw f' ()
2
>>> kw f' (Label :: Label "a") 10 ()
10

class IsKeyFN (t :: *) (flag :: Bool) | t -> flag Source #

All our keywords must be registered

Instances

(~) Bool False flag => IsKeyFN t flag Source #

overlapping/fallback case

(~) * r (c -> b) => IsKeyFN (K k s c -> r) True Source #

The purpose of this instance is to be able to use the same Symbol (type-level string) at different types. If they are supposed to be the same, then use Label instead of K

>>> let kA = K :: forall t. K "a" t
>>> let testF (K :: K "a" Int) a1 (K :: K "a" Integer) a2 () = a1-fromIntegral a2

therefore the following options works:

>>> kw (hBuild testF) kA (5 :: Int) kA (3 :: Integer) ()
2
>>> kw (hBuild testF) (K :: K "a" Integer) 3 (K :: K "a" Int) 5 ()
2

But you cannot leave off all Int or Integer annotations.

data K s (c :: *) Source #

Instances

(~) * r (c -> b) => IsKeyFN (K k s c -> r) True Source #

The purpose of this instance is to be able to use the same Symbol (type-level string) at different types. If they are supposed to be the same, then use Label instead of K

>>> let kA = K :: forall t. K "a" t
>>> let testF (K :: K "a" Int) a1 (K :: K "a" Integer) a2 () = a1-fromIntegral a2

therefore the following options works:

>>> kw (hBuild testF) kA (5 :: Int) kA (3 :: Integer) ()
2
>>> kw (hBuild testF) (K :: K "a" Integer) 3 (K :: K "a" Int) 5 ()
2

But you cannot leave off all Int or Integer annotations.

Labels

By labels, we mean either the first argument to Tagged (in the type-level lists that are supplied to Record, RecordU, TIP, TIC), or the expressions used to specify those types to be able to look up the correct value in those collections.

Nearly all types can be labels. For example:

    r :: Record '[Tagged "x" Int,   -- kind GHC.TypeLits.Symbol 
                  Tagged () (),    -- see Data.HList.Label5
                  Tagged (Lbl HZero LabelUniverse LabelMember1) () -- Label3
                 ]
    r = hBuild 8 () () -- don't need to use .=. / .==. and .*.
                          -- if we have a type signature above
  

we could define these variables

   xLabel = Label :: Label "x" -- makeLabels6 ["x"] would define x with the same RHS
   xLens  = hLens' xLabel        -- makeLabelable "x" would define x with the same RHS
  

to access the 8 given above:

   r .!. xLabel
   r  ^.   xLens   -- alternatively Control.Lens.view
   r  ^. `x        -- with HListPP is used (not in ghci),
                   -- which avoids the issue of conflicting
                   -- definitions of x, which mean the same
                   -- thing
  

Instances from Data.HList.Label6

>>> :set -XDataKinds
>>> (Label :: Label "x") .=. (5::Int) .*. emptyRecord
Record{x=5}
>>> let x = Label :: Label "x"
>>> let r = x .=. (5::Int) .*. emptyRecord
>>> r .!. x
5

Rather than having the x = Label :: Label "x", the labels generated by makeLabelable also double as lenses for Control.Lens. Here is an example of how much better that is:

>>> :set -XNoMonomorphismRestriction -XDataKinds -XPolyKinds
>>> import Control.Lens
>>> import Data.HList.Labelable
>>> let x = hLens' (Label :: Label "x")
>>> let y = hLens' (Label :: Label "y")

The Label6 method:

>>> let r = (Label :: Label "x") .=. "5" .*. emptyRecord

The Labelable way:

>>> let r2 = x .==. "5" .*. emptyRecord
>>> r ^. x
"5"
>>> r2 ^. x
"5"
>>> r & x .~ ()
Record{x=()}

When a field is missing, the error names that field:

>>> :t r^.y
...
...No instance for (Fail (FieldNotFound "y"))
...

Data.HList.Dredge

lenses

dredge :: (EnsureLabel x (Label k2 l), HSingleton ErrorMessage ErrorMessage [*] (NonUnique * * k2 r v l) (TypesDontMatch * [[*]] [*] * r ns1 vs1 v) ns2 xs, HGuardNonNull ErrorMessage [*] (NamesDontMatch * [[*]] k2 r ns l) ns1, FilterVEq1 [*] v vs1 ns1 ns2, FilterLastEq * * (Label k2 l) ns vs vs1, FilterLastEq * [*] (Label k2 l) ns ns ns1, MapFieldTreeVal r (TryCollectionListTF r) vs, MapFieldTree (TryCollectionListTF r) ns, LabelablePath xs (p v fb) (p r rft), SameLength' [*] * ns vs, SameLength' [*] * ns1 vs1, SameLength' * [*] vs ns, SameLength' * [*] vs1 ns1) => x -> p v fb -> p r rft Source #

Using HListPP syntax for short hand, dredge `foo expands out to something like `path . `to . `foo, with the restriction that there is only one possible `path . `to which leads to the label foo.

For example, if we have the following definitions,

type BVal a = Record '[Tagged "x" a, Tagged "a" Char]
type R a = Record  [Tagged "a" Int, Tagged "b" (BVal a)]
type V a = Variant [Tagged "a" Int, Tagged "b" (BVal a)]
lx = Label :: Label "x"

Then we have:

dredge `x :: Lens (R a) (R b) a b
dredge lx :: Lens (R a) (R b) a b
dredge `x :: Traversal (V a) (V b) a b -- there were only variants along the path we'd get a Prism
dredge lx :: Traversal (V a) (V b) a b
result-type directed operations are supported

There are two ways to access a field with tag a in the R type defined above, but they result in fields with different types being looked up:

`a        :: Lens' (R a) Char
`b . `a   :: Lens' (R a) Int

so provided that the result type is disambiguated by the context, the following two types can happen

dredge `a :: Lens' (R a) Char
dredge `a :: Lens' (R a) Int
TIP & TIC

type indexed collections are allowed along those paths, but as explained in the Labelable instances, only simple optics (Lens' Prism' Traversal' ) are produced. dredgeTI' works better if the target is a TIP or TIC

dredge' :: (SameLength' * [*] vs1 ns1, SameLength' * [*] vs ns, SameLength' [*] * ns1 vs1, SameLength' [*] * ns vs, LabelablePath xs (p a (f a)) (p s (f s)), MapFieldTree (TryCollectionListTF s) ns, MapFieldTreeVal s (TryCollectionListTF s) vs, FilterLastEq * [*] (Label k l) ns ns ns1, FilterLastEq * * (Label k l) ns vs vs1, FilterVEq1 [*] a vs1 ns1 ns2, HGuardNonNull ErrorMessage [*] (NamesDontMatch * [[*]] k s ns l) ns1, HSingleton ErrorMessage ErrorMessage [*] (NonUnique * * k s a l) (TypesDontMatch * [[*]] [*] * s ns1 vs1 a) ns2 xs, EnsureLabel x (Label k l)) => x -> p a (f a) -> p s (f s) Source #

dredge except a simple (s ~ t, a ~ b) optic is produced

dredgeND :: (EnsureLabel x (Label k2 l), HSingleton ErrorMessage ErrorMessage [*] (NonUnique' * k2 r l) (NamesDontMatch * [[*]] k2 r ns l) ns' xs, FilterLastEq * [*] (Label k2 l) ns ns ns', MapFieldTree (TryCollectionListTF r) ns, LabelablePath xs (p a fb) (p r rft)) => x -> p a fb -> p r rft Source #

dredgeND (named directed only) is the same as dredge, except the result type (a) is not used when the label would otherwise be ambiguous. dredgeND might give better type errors, but otherwise there should be no reason to pick it over dredge

dredgeND' :: (LabelablePath xs (p a (f a)) (p s (f s)), MapFieldTree (TryCollectionListTF s) ns, FilterLastEq * [*] (Label k l) ns ns ns', HSingleton ErrorMessage ErrorMessage [*] (NonUnique' * k s l) (NamesDontMatch * [[*]] k s ns l) ns' xs, EnsureLabel x (Label k l)) => x -> p a (f a) -> p s (f s) Source #

dredgeND except a simple (s ~ t, a ~ b) optic is produced

dredgeTI' :: (HSingleton ErrorMessage ErrorMessage [*] (NonUnique' * * s a) (NamesDontMatch * [[*]] * s ns a) ns' xs, FilterLastEq * [*] (Label * a) ns ns ns', MapFieldTree (TryCollectionListTF s) ns, LabelablePath xs (p a (f a)) (p s (f s))) => q a -> p a (f a) -> p s (f s) Source #

The same as dredgeND', except intended for TIP/TICs because the assumption is made that l ~ v for the Tagged l v elements. In other words, ticPrism' and tipyLens' could usually be replaced by

dredgeTI' :: _ => Label a -> Lens'  (TIP s) a
dredgeTI' :: _ => Label a -> Prism' (TIC s) a

where we might have s ~ '[Tagged a a, Tagged b b]

plain lookup

hLookupByLabelDredge :: (HSingleton ErrorMessage ErrorMessage [*] (NonUnique' * k r2 l) (NamesDontMatch * [[*]] k r2 ns l) ns' ls, FilterLastEq * [*] (Label k l) ns ns ns', MapFieldTree (TryCollectionListTF r2) ns, HasFieldPath False ls (r1 r2) v) => Label k l -> r1 r2 -> v Source #

class HasFieldPath (needJust :: Bool) (ls :: [*]) r v | needJust ls r -> v Source #

Minimal complete definition

hLookupByLabelPath1

Instances

HasFieldPath False ([] *) v v Source # 

Methods

hLookupByLabelPath1 :: Proxy Bool False -> Label [*] [*] -> v -> v Source #

HasFieldPath True ([] *) v (Maybe v) Source # 

Methods

hLookupByLabelPath1 :: Proxy Bool True -> Label [*] [*] -> v -> Maybe v Source #

(HasField k l (Record r) u, HasFieldPath needJust ls u v) => HasFieldPath needJust ((:) * (Label k l) ls) (Record r) v Source # 

Methods

hLookupByLabelPath1 :: Proxy Bool needJust -> Label [*] ((* ': Label k l) ls) -> Record r -> v Source #

(HasField k l (Variant r) (Maybe u), HasFieldPath True ls u (Maybe v)) => HasFieldPath needJust ((:) * (Label k l) ls) (Variant r) (Maybe v) Source # 

Methods

hLookupByLabelPath1 :: Proxy Bool needJust -> Label [*] ((* ': Label k l) ls) -> Variant r -> Maybe v Source #

namespaced labels

labels as any instance of Typeable

template haskell

Data.HList.Data

This modules provide useful instances. A useful application can be found in examples/cmdargs.hs

Overlapping instances are restricted to here

Internals

internals exported for type signature purposes

class HAllTaggedEq (l :: [*]) Source #

Instances

HAllTaggedEq ([] *) Source # 
(HAllTaggedEq l, (~) * tee (Tagged k e e')) => HAllTaggedEq ((:) * tee l) Source #