HList 0.2.1 → 0.2.2
raw patch · 28 files changed
+642/−340 lines, 28 filesdep +template-haskellPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: template-haskell
API changes (from Hackage documentation)
- Data.HList.HZip: class HZippable x y
- Data.HList.HZip: instance [overlap ok] (HZippable l l') => HZippable (HCons e l) (HCons e' l')
- Data.HList.HZip: instance [overlap ok] HZippable HNil HNil
+ Data.HList.GhcSyntax: (.+.) :: (HExtend (Proxy e) l l') => e -> l -> l'
+ Data.HList.GhcSyntax: (.-.) :: (H2ProjectByLabels (HCons e HNil) r _r' r') => Record r -> e -> Record r'
+ Data.HList.GhcSyntax: (.<++.) :: (HLeftUnion r r' r'') => r -> r' -> r''
+ Data.HList.GhcSyntax: (.<.) :: (HasField t t2 t1, HUpdateAtHNat n (LVPair t t1) t2 l', HFind t ls n, RecordLabels t2 ls) => LVPair t t1 -> Record t2 -> Record l'
+ Data.HList.GhcSyntax: (.@.) :: (HUpdateAtHNat n (LVPair t t1) t2 l', HFind t ls n, RecordLabels t2 ls) => LVPair t t1 -> Record t2 -> Record l'
+ Data.HList.GhcSyntax: (.^.) :: (HUpdateAtHNat n (LVPair t t1) t2 l', HFind t ls n, RecordLabels t2 ls, HasField t t2 (Proxy t1)) => LVPair t t1 -> Record t2 -> Record l'
+ Data.HList.MakeLabels: instance [overlap ok] ReplaceSyntax Dec
+ Data.HList.MakeLabels: instance [overlap ok] ReplaceSyntax Exp
+ Data.HList.MakeLabels: instance [overlap ok] ReplaceSyntax Type
+ Data.HList.MakeLabels: instance [overlap ok] ReplaceSyntax [Dec]
+ Data.HList.MakeLabels: label :: String -> Q [Dec]
+ Data.HList.MakeLabels: makeLabels :: [String] -> Q [Dec]
+ Data.HList.Record: hDeleteAtLabel :: (H2ProjectByLabels (HCons e HNil) t t1 t2) => e -> Record t -> Record t2
+ Data.HList.Record: hProjectByLabels2 :: (H2ProjectByLabels ls t t1 t2, HRLabelSet t1, HRLabelSet t2) => ls -> Record t -> (Record t1, Record t2)
+ Data.HList.Record: 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)
+ Data.HList.Record: 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'
+ Data.HList.Record: hUpdateAtLabel :: (HUpdateAtHNat n (LVPair l v) t l', HFind l ls n, RecordLabels t ls) => l -> v -> Record t -> Record l'
Files
- Data/HList.hs +1/−1
- Data/HList/CommonMain.hs +1/−1
- Data/HList/FakePrelude.hs +25/−19
- Data/HList/GhcRecord.hs +17/−11
- Data/HList/GhcSyntax.hs +73/−61
- Data/HList/HArray.hs +19/−14
- Data/HList/HListPrelude.hs +75/−56
- Data/HList/HOccurs.hs +14/−19
- Data/HList/HTypeIndexed.hs +8/−8
- Data/HList/HZip.hs +9/−11
- Data/HList/Label1.hs +7/−7
- Data/HList/Label2.hs +10/−7
- Data/HList/Label3.hs +10/−7
- Data/HList/Label4.hs +6/−3
- Data/HList/Label5.hs +5/−3
- Data/HList/MakeLabels.hs +108/−0
- Data/HList/Record.hs +172/−47
- Data/HList/RecordP.hs +2/−1
- Data/HList/TIC.hs +6/−6
- Data/HList/TIP.hs +44/−37
- Data/HList/TypeCastGeneric1.hs +1/−1
- Data/HList/TypeCastGeneric2.hs +3/−2
- Data/HList/TypeEqBoolGeneric.hs +1/−1
- Data/HList/TypeEqGeneric1.hs +2/−2
- Data/HList/TypeEqGeneric2.hs +2/−2
- Data/HList/Variant.hs +6/−6
- HList.cabal +5/−3
- README +10/−4
Data/HList.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE MagicHash #-}-{-+{- | OOHaskell (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke This module gathers the API that we need for OOP in Haskell. We
Data/HList/CommonMain.hs view
@@ -1,4 +1,4 @@-{-+{- | The HList library
Data/HList/FakePrelude.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE EmptyDataDecls, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -13,7 +13,7 @@ {-----------------------------------------------------------------------------} --- Type-level Booleans+-- * Booleans data HTrue; hTrue :: HTrue; hTrue = undefined data HFalse; hFalse :: HFalse; hFalse = undefined@@ -22,7 +22,7 @@ instance Show HFalse where show _ = "HFalse" --- Conjunction of type-level Booleans+-- ** Conjunction class (HBool t, HBool t', HBool t'') => HAnd t t' t'' | t t' -> t'' where@@ -45,7 +45,7 @@ hAnd _ _ = hTrue --- Disjunction of type-level Booleans+-- ** Disjunction class (HBool t, HBool t', HBool t'') => HOr t t' t'' | t t' -> t'' where@@ -68,7 +68,7 @@ hOr _ _ = hTrue --- Type-level conditional+-- ** Conditional class HBool t => HCond t x y z | t x y -> z where@@ -89,7 +89,7 @@ {-----------------------------------------------------------------------------} --- Type-level naturals+-- * Naturals data HZero data HSucc n@@ -123,7 +123,7 @@ {-----------------------------------------------------------------------------} --- Type-level maybies+-- * Maybies data HNothing = HNothing deriving Show data HJust x = HJust x deriving Show@@ -131,11 +131,10 @@ {-----------------------------------------------------------------------------} --- Equality for types+-- * Equality for types class HBool b => HEq x y b | x y -> b - -- Equality instances for naturals instance HEq HZero HZero HTrue@@ -150,9 +149,12 @@ {-----------------------------------------------------------------------------} --- Staged equality--- - Establish type equality statically--- - Establish remaining value-level equality dynamically+-- * Staged equality+-- |+--+-- * Establish type equality statically+--+-- * Establish remaining value-level equality dynamically class HStagedEq x y where@@ -161,7 +163,7 @@ {-----------------------------------------------------------------------------} --- Less than+-- | Less than class HBool b => HLt x y b | x y -> b @@ -180,8 +182,10 @@ {-----------------------------------------------------------------------------} --- A predicate for type equality+-- | A predicate for type equality+-- -- There are different implementations.+-- -- See imports in Main*.hs class HBool b => TypeEq x y b | x y -> b@@ -199,7 +203,7 @@ {-----------------------------------------------------------------------------} --- Type-safe cast+-- * Type-safe cast class TypeCast x y | x -> y, y -> x where@@ -208,7 +212,7 @@ {-----------------------------------------------------------------------------} --- A phantom type for type proxies+-- * A phantom type for type proxies data Proxy e instance Show (Proxy e) where show _ = "Proxy"@@ -225,7 +229,7 @@ {-----------------------------------------------------------------------------} --- Type equality and disequality+-- * Type equality and disequality class TypeEqTrue x y class TypeEqFalse x y@@ -239,7 +243,7 @@ {-----------------------------------------------------------------------------} --- Subtyping+-- * Subtyping class SubType l l' @@ -249,7 +253,9 @@ {-----------------------------------------------------------------------------} --- A class without instances for explicit failure+-- * Error messages++-- | A class without instances for explicit failure class Fail x
Data/HList/GhcRecord.hs view
@@ -7,14 +7,14 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke Extensible records -- operations that (may) require GHC - See Record.hs for the base module.+ See "Data.HList.Record" for the base module. -} module Data.HList.GhcRecord where@@ -28,7 +28,8 @@ {-----------------------------------------------------------------------------} --- A variation on update.+-- | A variation on update.+-- -- Replace a proxy by a value of the proxied type. -- The signature is inferred hUnproxyLabel :: (HUpdateAtHNat n (LVPair l a) t l', HFind l ls n,@@ -44,7 +45,7 @@ {-----------------------------------------------------------------------------} --- Test for values; refuse proxies+-- | Test for values; refuse proxies hasNoProxies :: HasNoProxies r => Record r -> ()@@ -61,8 +62,8 @@ {-----------------------------------------------------------------------------} --- Narrow a record to a different record type-+-- | Narrow a record to a different record type+-- -- First is the `monadic' version, which returns the `failure indictator' -- (HNothing) if the narrowing fails because the source does not have -- all the fields for the target.@@ -119,7 +120,7 @@ {-----------------------------------------------------------------------------} --- Narrow two records to their least-upper bound+-- | Narrow two records to their least-upper bound class LubNarrow a b c | a b -> c where@@ -142,7 +143,7 @@ {-----------------------------------------------------------------------------} --- List constructors that also LUB together+-- | List constructors that also LUB together data NilLub nilLub :: NilLub@@ -165,7 +166,7 @@ {-----------------------------------------------------------------------------} --- Extension of lubNarrow to a heterogeneous list+-- | Extension of lubNarrow to a heterogeneous list class HLub l e | l -> e where@@ -196,18 +197,23 @@ {-----------------------------------------------------------------------------}--- Record equivalence modulo field order+-- | Record equivalence modulo field order+-- -- Decide if two records r1 and r2 are identical or differ only in the order -- of their fields.+-- -- If the two record types are indeed equivalent, return the witness of -- their equivalence, (HJust (r1->r2,r2->r1)). If they are not equivalent, -- return HNothing+-- -- The function equivR does not examine the values of its arguments: -- it needs only their types.-+--+-- -- The algorithm is simple: two records are equivalent if one can be narrowed -- to the other, and vice versa. The narrowing coercions are the desired -- witnesses.+-- -- The obvious optimization is to check first if two records are of the same -- type. That requires TypeEq however. Perhaps we shouldn't use it here. -- Use of the record narrowing tacitly assumes that the label of a record
Data/HList/GhcSyntax.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE TypeOperators #-}-{-# OPTIONS_GHC -fno-warn-missing-signatures #-} {-# LANGUAGE FlexibleContexts #-}-{-+{- | (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke Some dedicated infix operators at the type and the value level.@@ -13,123 +12,135 @@ import Data.HList.HListPrelude import Data.HList.Record import Data.HList.GhcRecord+import Data.HList.HArray {-----------------------------------------------------------------------------} --- Convenience notation for type sequences+-- * For types infixr 2 :*: infixr 2 .*. type e :*: l = HCons e l -{-| - (.*.) -- Add a field to a record. Analagous to (++) for- lists. +infixr 4 :=:+type l :=: v = LVPair l v - record .*. field1- .*. field2---}-(.*.) :: HExtend e l l' => e -> l -> l'-(.*.) = hExtend+infixr 4 .=. {-----------------------------------------------------------------------------} --- Convenience notation for records--- Many signatures are deliberately omitted. They should be inferred.--- There is no point of writing the same thing in terms and in types.+-- * For records -infixr 4 :=:-type l :=: v = LVPair l v+{-| -infixr 4 .=.+ [@(.*.)@]+ Add a field to a record. Analagous to (++) for+ lists.++ > record .*. field1+ > .*. field2++-}+(.*.) :: HExtend e l l' => e -> l -> l'+(.*.) = hExtend+ {-| - (.=.) -- Create a value with the given label. Analagous to a data- constructor such as 'Just', 'Left', or 'Right'. Higher fixity- than record-modification operations like (.*.), (.-.), etc. to- support expression like the below w/o parentheses:+ Create a value with the given label. Analagous to a data+ constructor such as 'Just', 'Left', or 'Right'. Higher fixity+ than record-modification operations like (.*.), (.-.), etc. to+ support expression like the below w/o parentheses: - label1 .=. value1 .*. - label2 .=. value2 .*. - emptyRecord+ > label1 .=. value1 .*.+ > label2 .=. value2 .*.+ > emptyRecord ---}+-} (.=.) :: l -> v -> LVPair l v l .=. v = newLVPair l v infixr 9 .!. {-|- (.!.) -- Lookup a value in a record, by its label. Analagous to (!!), the- list indexing operation. Highest fixity, like (!!).+ Lookup a value in a record, by its label. Analagous to (!!), the+ list indexing operation. Highest fixity, like (!!). - record1 .*. label1 .=. record2 .!. label1- .*. label2 .=. record2 .!. label2---}+ > record1 .*. label1 .=. record2 .!. label1+ > .*. label2 .=. record2 .!. label2++-} (.!.) :: (HasField l r v) => r -> l -> v r .!. l = hLookupByLabel l r infixl 2 .-. {-|- (.-.) -- Remove a field from a record. At the same- level as other record modification options (.*.). Analagous- to (\\) in lists.+ Remove a field from a record. At the same+ level as other record modification options (.*.). Analagous+ to (\\) in lists. - record1 .-. label1+ > record1 .-. label1 - label1 .=. value1 .*. - label2 .=. value2 .-.- label2 .*. - emptyRecord + > label1 .=. value1 .*.+ > label2 .=. value2 .-.+ > label2 .*.+ > emptyRecord - label1 .=. value1 .-.- label1 .*. - label2 .=. value2 .*. - emptyRecord + > label1 .=. value1 .-.+ > label1 .*.+ > label2 .=. value2 .*.+ > emptyRecord - record1 .*. label1 .=. record2 .!. label1- .*. label2 .=. record2 .!. label2 - .-. label1---}+ > record1 .*. label1 .=. record2 .!. label1+ > .*. label2 .=. record2 .!. label2+ > .-. label1++-}+(.-.) :: (H2ProjectByLabels (HCons e HNil) r _r' r') =>+ Record r -> e -> Record r' r .-. l = hDeleteAtLabel l r infixr 2 .@. {-|- (.@.) -- Update a field with a particular value.- Same fixity as (.*.) so that extensions and updates can be chained.- There is no real list analogue, since there is no Prelude defined- update. - label1 .=. value1 .@. record1 + Update a field with a particular value.+ Same fixity as (.*.) so that extensions and updates can be chained.+ There is no real list analogue, since there is no Prelude defined+ update. + > label1 .=. value1 .@. record1+ -}+(.@.) :: (HUpdateAtHNat n (LVPair t t1) t2 l',HFind t ls n,RecordLabels t2 ls) =>LVPair t t1 -> Record t2 -> Record l' f@(LVPair v) .@. r = hUpdateAtLabel (labelLVPair f) v r infixr 2 .^. {-|-- (.^.) -- This is a variation on updating (according to GhcRecord.hs),- so use the same fixity as (.\@.).+ This is a variation on updating (according to GhcRecord.hs),+ so use the same fixity as (.\@.). -}+(.^.) :: (HUpdateAtHNat n (LVPair t t1) t2 l',HFind t ls n,RecordLabels t2 ls,HasField t t2 (Proxy t1)) =>LVPair t t1 -> Record t2 -> Record l' f@(LVPair v) .^. r = hUnproxyLabel (labelLVPair f) v r infixr 2 .<.-{-| - (.<.) -- Another variation on update, so give it the same fixity as (.\@.).+{-|+ Another variation on update, so give it the same fixity as (.\@.). -}+(.<.) :: (HasField t t2 t1,HUpdateAtHNat n (LVPair t t1) t2 l',HFind t ls n,RecordLabels t2 ls) =>LVPair t t1 -> Record t2 -> Record l' f@(LVPair v) .<. r = hTPupdateAtLabel (labelLVPair f) v r infixl 1 .<++. {-|- (.<++.) -- Similar to list append, so give this slightly lower fixity than- (.*.), so we can write:+ Similar to list append, so give this slightly lower fixity than+ (.*.), so we can write: - field1 .=. value .*. record1 .<++. record2+ > field1 .=. value .*. record1 .<++. record2+ -}+(.<++.) :: (HLeftUnion r r' r'') => r -> r' -> r'' r .<++. r' = hLeftUnion r r' @@ -143,9 +154,10 @@ type e :+: l = HCons (Proxy e) l {-|- (.+.) -- Type-indexed rows append. Very similar to .*., so - keep the same fixity.+ Type-indexed rows append. Very similar to (.*.), so+ keep the same fixity. -}+(.+.) :: (HExtend (Proxy e) l l') => e -> l -> l' e .+. r = hExtend (toProxy e) r
Data/HList/HArray.hs view
@@ -1,7 +1,7 @@ {-# OPTIONS_GHC -fno-warn-missing-signatures #-} {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, FlexibleContexts, UndecidableInstances #-}-{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -17,7 +17,7 @@ {-----------------------------------------------------------------------------} --- A lookup operation+-- * Lookup class HNat n => HLookupByHNat n l e | n l -> e where@@ -35,7 +35,7 @@ {-----------------------------------------------------------------------------} --- A delete operation+-- * Delete class HNat n => HDeleteAtHNat n l l' | n l -> l' where@@ -53,7 +53,7 @@ {-----------------------------------------------------------------------------} --- An update operation+-- * Update class HNat n => HUpdateAtHNat n e l l' | n e l -> l', l' n -> e where@@ -72,10 +72,13 @@ {-----------------------------------------------------------------------------} --- Splitting an array according to indices+-- * Splitting+-- | Splitting an array according to indices+-- -- Signature is inferred:--- hSplitByHNats :: (HSplitByHNats' ns l' l'1 l'', HMap (HAddTag HTrue) l l') =>--- ns -> l -> (l'1, l'')+--+-- > hSplitByHNats :: (HSplitByHNats' ns l' l'1 l'', HMap (HAddTag HTrue) l l') =>+-- > ns -> l -> (l'1, l'') hSplitByHNats ns l = hSplitByHNats' ns (hFlag l) class HNats ns => HSplitByHNats' ns l l' l'' | ns l -> l' l''@@ -104,7 +107,7 @@ {-----------------------------------------------------------------------------} --- Another projection operation+-- * Projection class HNats ns => HProjectByHNats ns l l' | ns l -> l' where@@ -130,7 +133,7 @@ {-----------------------------------------------------------------------------} --- The complement of projection+-- * Complement of Projection class HProjectAwayByHNats ns l l' | ns l -> l' where@@ -153,7 +156,8 @@ {-----------------------------------------------------------------------------} --- Generate naturals from 1 to x - 1+-- * Enumerate naturals+-- | from 1 to x - 1 class HBetween x y | x -> y where@@ -173,7 +177,7 @@ hBetween x = hBetween (hPred x) `hAppend` HCons (hPred x) HNil --- Set-difference on naturals+-- * Set-difference on naturals class HDiff x y z | x y -> z where@@ -195,7 +199,8 @@ z = hDiff x y --- Membership test for types with HOrd instances+-- * Membership test for types with 'HOrd' instances+-- | -- This special type equality/comparison is entirely pure! class HOrdMember e l b | e l -> b@@ -220,7 +225,7 @@ {-----------------------------------------------------------------------------} --- Length operation+-- * Length class (HList l, HNat n) => HLength l n | l -> n instance HLength HNil HZero@@ -233,7 +238,7 @@ {-----------------------------------------------------------------------------} --- Bounded lists+-- * Bounded lists class HMaxLength l s instance (HLength l s', HLt s' (HSucc s) HTrue) => HMaxLength l s
Data/HList/HListPrelude.hs view
@@ -1,12 +1,16 @@ {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances, FlexibleContexts #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke Basic declarations for typeful heterogeneous lists.++ Excuse the unstructured haddocks: while there are many declarations here+ some are alternative implementations should be grouped, and the definitions+ here are analgous to many list functions in the "Prelude". -} module Data.HList.HListPrelude where@@ -15,7 +19,7 @@ {-----------------------------------------------------------------------------} --- Heterogeneous type sequences+-- * Heterogeneous type sequences data HNil = HNil deriving (Eq,Show,Read) data HCons e l = HCons e l deriving (Eq,Show,Read)@@ -23,7 +27,7 @@ {-----------------------------------------------------------------------------} --- The set of all types of heterogeneous lists+-- * The set of all types of heterogeneous lists class HList l instance HList HNil@@ -32,7 +36,7 @@ {-----------------------------------------------------------------------------} --- Public constructors+-- * Public constructors hNil :: HNil hNil = HNil@@ -43,7 +47,7 @@ {-----------------------------------------------------------------------------} --- Basic list functions+-- * Basic list functions class HHead l h | l -> h where@@ -65,7 +69,7 @@ {-----------------------------------------------------------------------------} --- A class for extension+-- * A class for extension class HExtend e l l' | e l -> l', l' -> e l where@@ -82,23 +86,23 @@ {-----------------------------------------------------------------------------} --- Appending HLists+-- * Appending HLists --- The normal append for comparison+-- | The normal append for comparison append :: [a] -> [a] -> [a] append [] l = l append (x:l) l' = x : append l l' --- The class HAppend+-- | The class HAppend class HAppend l l' l'' | l l' -> l'' where hAppend :: l -> l' -> l'' --- The instance following the normal append+-- | The instance following the normal append instance HList l => HAppend HNil l l where@@ -112,7 +116,7 @@ {-----------------------------------------------------------------------------} --- Reversing HLists+-- * Reversing HLists class HReverse l1 l2 | l1 -> l2, l2 -> l1 where@@ -140,7 +144,7 @@ hReverse' l1 (HCons a l2') = hReverse' (HCons a l1) l2' --- Naive HReverse+-- ** Naive HReverse class NaiveHReverse l l' | l -> l' where@@ -162,23 +166,23 @@ {-----------------------------------------------------------------------------} ----- A nicer notation for lists+-- * A nicer notation for lists -- --- List termination+-- | List termination hEnd :: HCons t t1 -> HCons t t1 hEnd t@(HCons _ _) = t -{-+{- ^ Note:- - x :: HCons a b- means: forall a b. x :: HCons a b- - hEnd x- means: exists a b. x :: HCons a b++ [@x :: HCons a b@] means: @forall a b. x :: HCons a b@++ [@hEnd x@] means: @exists a b. x :: HCons a b@ -} --- Building non-empty lists+-- ** Building non-empty lists hBuild :: (HBuild' HNil a r) => a -> r hBuild x = hBuild' HNil x@@ -197,28 +201,28 @@ where hBuild' l x y = hBuild' (HCons x l) y -{-+{- $hbuild -HList> let x = hBuild True in hEnd x-HCons True HNil+> HList> let x = hBuild True in hEnd x+> HCons True HNil -HList> let x = hBuild True 'a' in hEnd x-HCons True (HCons 'a' HNil)+> HList> let x = hBuild True 'a' in hEnd x+> HCons True (HCons 'a' HNil) -HList> let x = hBuild True 'a' "ok" in hEnd x-HCons True (HCons 'a' (HCons "ok" HNil))+> HList> let x = hBuild True 'a' "ok" in hEnd x+> HCons True (HCons 'a' (HCons "ok" HNil)) -HList> hEnd (hBuild (Key 42) (Name "Angus") Cow (Price 75.5))-HCons (Key 42) (HCons (Name "Angus") (HCons Cow (HCons (Price 75.5) HNil)))+> HList> hEnd (hBuild (Key 42) (Name "Angus") Cow (Price 75.5))+> HCons (Key 42) (HCons (Name "Angus") (HCons Cow (HCons (Price 75.5) HNil))) -HList> hEnd (hBuild (Key 42) (Name "Angus") Cow (Price 75.5)) == angus-True+> HList> hEnd (hBuild (Key 42) (Name "Angus") Cow (Price 75.5)) == angus+> True -} {-----------------------------------------------------------------------------} --- A heterogeneous apply operator+-- * A heterogeneous apply operator class Apply f a r | f a -> r where apply :: f -> a -> r@@ -226,13 +230,13 @@ -- type-level computations only --- Normal function application+-- | Normal function application instance Apply (x -> y) x y where apply f x = f x --- Identity+-- | Identity data Id = Id @@ -242,7 +246,7 @@ {-----------------------------------------------------------------------------} --- A heterogeneous fold for all types+-- * A heterogeneous fold for all types class HList l => HFoldr f v l r | f v l -> r where@@ -262,6 +266,8 @@ {-----------------------------------------------------------------------------} +-- * Map+ class HMap f l l' | f l -> l' where hMap :: f -> l -> l'@@ -280,7 +286,7 @@ {-----------------------------------------------------------------------------} --- Map a heterogeneous list to a homogeneous one+-- * Map a heterogeneous list to a homogeneous one class HMapOut f r e where@@ -300,9 +306,13 @@ {-----------------------------------------------------------------------------} --- A heterogenous version of mapM.--- mapM :: forall b m a. (Monad m) => (a -> m b) -> [a] -> m [b]+-- * A heterogenous version of mapM.+--+-- > mapM :: forall b m a. (Monad m) => (a -> m b) -> [a] -> m [b]+-- -- Likewise for mapM_.+--+-- See "Data.HList.HSequence" if the result list should also be heterogenous. hMapM :: (Monad m, HMapOut f l (m e)) => f -> l -> [m e] hMapM f = hMapOut f@@ -321,11 +331,12 @@ {-----------------------------------------------------------------------------} --- A reconstruction of append+-- * A reconstruction of append append' :: [a] -> [a] -> [a] append' l l' = foldr (:) l' l +-- | Alternative implementation of 'hAppend'. Demonstrates 'HFoldr' hAppend' :: (HFoldr ApplyHCons v l r) => l -> v -> r hAppend' l l' = hFoldr ApplyHCons l' l @@ -338,10 +349,11 @@ {-----------------------------------------------------------------------------} --- A heterogeneous map for all types+-- * A heterogeneous map for all types data HMap' f = HMap' f +-- | Same as 'hMap' only a different implementation. hMap' :: (HFoldr (HMap' f) HNil l r) => f -> l -> r hMap' f = hFoldr (HMap' f) hNil @@ -355,7 +367,7 @@ {-----------------------------------------------------------------------------} --- A function for showing+-- * A function for showing data HShow = HShow data HSeq x = HSeq x@@ -374,7 +386,7 @@ {-----------------------------------------------------------------------------} --- Type-level equality for lists+-- * Type-level equality for lists instance HEq HNil HNil HTrue instance HList l => HEq HNil (HCons e l) HFalse@@ -385,7 +397,7 @@ {-----------------------------------------------------------------------------} --- Staged equality for lists+-- * Staged equality for lists instance HStagedEq HNil HNil where@@ -426,21 +438,21 @@ {-----------------------------------------------------------------------------} --- Ensure a list to contain HNats only+-- * Ensure a list to contain HNats only class HList l => HNats l instance HNats HNil instance (HNat n, HNats ns) => HNats (HCons n ns) --- Static set property based on HEq+-- * Static set property based on HEq class HSet l instance HSet HNil instance (HMember e l HFalse, HSet l) => HSet (HCons e l) --- Find an element in a set based on HEq+-- * Find an element in a set based on HEq class HNat n => HFind e l n | e l -> n where hFind :: e -> l -> n@@ -469,7 +481,7 @@ hFind' _ e l = hSucc (hFind e l) --- Membership test+-- * Membership test class HBool b => HMember e l b | e l -> b instance HMember e HNil HFalse@@ -480,7 +492,8 @@ hMember _ _ = undefined --- Another type-level membership test+-- ** Another type-level membership test+-- -- Check to see if an element e occurs in a list l -- If not, return HNothing -- If the element does occur, return HJust l'@@ -499,7 +512,7 @@ --- Membership test based on type equality+-- ** Membership test based on type equality class HBool b => HTMember e l b | e l -> b instance HTMember e HNil HFalse@@ -510,10 +523,11 @@ hTMember _ _ = undefined --- Intersection based on HTMember+-- * Intersection based on HTMember class HTIntersect l1 l2 l3 | l1 l2 -> l3 where+ -- | Like 'Data.List.intersect' hTIntersect :: l1 -> l2 -> l3 instance HTIntersect HNil l HNil@@ -544,8 +558,9 @@ hTIntersectBool _ _ t l1 = hTIntersect t l1 --- Turn a heterogeneous list into a homogeneous one+-- * Turn a heterogeneous list into a homogeneous one +-- | Same as @hMapOut Id@ class HList2List l e where hList2List :: l -> [e]@@ -562,8 +577,10 @@ {-----------------------------------------------------------------------------} --- Turn list in a list of justs+-- * With 'HMaybe' +-- ** Turn list in a list of justs+ class ToHJust l l' | l -> l' where toHJust :: l -> l'@@ -579,7 +596,7 @@ {-----------------------------------------------------------------------------} --- Extract justs from list of maybes+-- ** Extract justs from list of maybes class FromHJust l l' | l -> l' where@@ -600,7 +617,7 @@ {-----------------------------------------------------------------------------} --- Annotated lists+-- * Annotated lists data HAddTag t = HAddTag t data HRmTag = HRmTag@@ -619,14 +636,16 @@ apply HRmTag (e,_) = e --- Annotate list with a type-level Boolean+-- | Annotate list with a type-level Boolean hFlag :: (HMap (HAddTag HTrue) l l') => l -> l' hFlag l = hAddTag hTrue l {-----------------------------------------------------------------------------} --- Splitting by HTrue and HFalse+-- * Splitting by HTrue and HFalse++-- | Analogus to @Data.List.partition snd@ class HSplit l l' l'' | l -> l' l'' where
Data/HList/HOccurs.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE EmptyDataDecls, MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, OverlappingInstances, UndecidableInstances #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -9,7 +9,9 @@ Result-type-driven operations on typeful heterogeneous lists. -} -module Data.HList.HOccurs where+module Data.HList.HOccurs (+ module Data.HList.HOccurs,+ ) where import Data.HList.FakePrelude import Data.HList.HListPrelude@@ -196,35 +198,28 @@ {-----------------------------------------------------------------------------} --- Illustration of typical test scenarios--{-+-- * Illustration of typical test scenarios+{- $example Retrieve the Breed of an animal. -ghci-or-hugs> hOccurs myAnimal :: Breed-Cow+> ghci-or-hugs> hOccurs myAnimal :: Breed+> Cow --} -{-- Normal hOccurs requires specification of the result type even if the result type is determined by the fact that we are faced with a singleton list. -ghci-or-hugs> hOccurs (HCons 1 HNil)+> ghci-or-hugs> hOccurs (HCons 1 HNil)+>+> <interactive>:1:+> No instance for (HOccurs e1 (HCons e HNil)) -<interactive>:1:- No instance for (HOccurs e1 (HCons e HNil)) --}--{-- However, hOccurs can be elaborated as improved as follows: -ghci-or-hugs> hLookup (HCons 1 HNil)-1+> ghci-or-hugs> hLookup (HCons 1 HNil)+> 1 -}
Data/HList/HTypeIndexed.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances, FlexibleContexts #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -56,13 +56,13 @@ {-----------------------------------------------------------------------------} --- Map a type to a natural+-- | Map a type to a natural class HNat n => HType2HNat e l n | e l -> n instance (TypeEq e' e b, HType2HNatCase b e l n) => HType2HNat e (HCons e' l) n --- Helper class+-- | Helper class class (HBool b, HNat n) => HType2HNatCase b e l n | b e l -> n instance HOccursNot e l => HType2HNatCase HTrue e l HZero@@ -73,7 +73,7 @@ --- Map types to naturals+-- | Map types to naturals class HTypes2HNats ps l ns | ps l -> ns where@@ -93,28 +93,28 @@ {-----------------------------------------------------------------------------} --- Define type-indexed delete in terms of the natural-based primitive+-- | Define type-indexed delete in terms of the natural-based primitive hDeleteAtProxy :: (HDeleteAtHNat n l l', HType2HNat e l n) => Proxy e -> l -> l' hDeleteAtProxy p l = hDeleteAtHNat (hType2HNat p l) l {-----------------------------------------------------------------------------} --- Define type-indexed update in terms of the natural-based update+-- | Define type-indexed update in terms of the natural-based update hUpdateAtType :: (HUpdateAtHNat n e l l', HType2HNat e l n) => e -> l -> l' hUpdateAtType e l = hUpdateAtHNat (hType2HNat (toProxy e) l) e l {-----------------------------------------------------------------------------} --- Projection based on proxies+-- | Projection based on proxies hProjectByProxies :: (HProjectByHNats ns l l', HTypes2HNats ps l ns) => ps -> l -> l' hProjectByProxies ps l = hProjectByHNats (hTypes2HNats ps l) l {-----------------------------------------------------------------------------} --- Splitting based on proxies+-- | Splitting based on proxies hSplitByProxies :: (HMap (HAddTag HTrue) l l', HSplitByHNats' ns l' l'1 l'', HTypes2HNats ps l ns) => ps -> l -> (l'1, l'')
Data/HList/HZip.hs view
@@ -4,7 +4,7 @@ import Data.HList.HListPrelude -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -14,16 +14,7 @@ {-----------------------------------------------------------------------------} --- Test for zippability--class HZippable x y-instance HZippable HNil HNil-instance HZippable l l' => HZippable (HCons e l) (HCons e' l')---{-----------------------------------------------------------------------------}---- Zip and unzip+-- | Zip and unzip class HZip x y l | x y -> l, l -> x y where@@ -33,6 +24,13 @@ {- -- Zipping version I++-- | Test for zippability: equal length.++class HZippable x y+instance HZippable HNil HNil+instance HZippable l l' => HZippable (HCons e l) (HCons e' l')+ -- Somehow too polymorphic. -- Version II specialises for HNil and HCons.
Data/HList/Label1.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-} -{-+{- | The HList library (C) 2004-2006, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -17,34 +17,34 @@ import Data.HList.Record (ShowLabel(..)) --- Labels are type-level naturals+-- | Labels are type-level naturals newtype Label x = Label x deriving Show --- Public constructors for labels+-- | Public constructors for labels label :: HNat n => n -> Label n label = Label --- Construct the first label+-- | Construct the first label firstLabel :: Label HZero firstLabel = label hZero --- Construct the next label+-- | Construct the next label nextLabel ::( HNat t) => Label t -> Label (HSucc t) nextLabel (Label n) = label (hSucc n) --- Equality on labels+-- | Equality on labels instance HEq n n' b => HEq (Label n) (Label n') b --- Show label+-- | Show label instance Show n => ShowLabel (Label n) where
Data/HList/Label2.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, EmptyDataDecls #-} -{-+{- | The HList library (C) 2004-2006, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -15,11 +15,14 @@ and description. The namespace part helps avoid confusions between labels from different Haskell modules. The description is an arbitrary nullary type constructor.+ For the sake of printing, the namespace part and the description are required to be the instance of Show. One must make sure that the show functions does not examine the value, as descr is purely phantom. Here's an example of the good Label description:- data MyLabelDescr; instance Show MyLabelDescr where show _ = "descr"++ > data MyLabelDescr; instance Show MyLabelDescr where show _ = "descr"+ which obviously can be automated with Template Haskell. This model requires all labels in a record to inhabit the same namespace.@@ -31,29 +34,29 @@ import Data.HList.Record (ShowLabel(..)) --- Labels are type-level naturals+-- | Labels are type-level naturals data Label x ns desc -- labels are exclusively type-level entities --- Construct the first label+-- | Construct the first label firstLabel :: ns -> desc -> Label HZero ns desc firstLabel = undefined --- Construct the next label+-- | Construct the next label nextLabel :: Label x ns desc -> desc' -> Label (HSucc x) ns desc' nextLabel = undefined --- Equality on labels (descriptions are ignored)+-- | Equality on labels (descriptions are ignored) instance HEq x x' b => HEq (Label x ns desc1) (Label x' ns desc2) b --- Show label+-- | Show label instance (HNat x, Show desc) => ShowLabel (Label x ns desc) where showLabel = show . getd
Data/HList/Label3.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, EmptyDataDecls #-} -{-+{- | The HList library (C) 2004-2006, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -15,11 +15,14 @@ and description. The namespace part helps avoid confusions between labels from different Haskell modules. The description is an arbitrary nullary type constructor.+ For the sake of printing, the description is required to be the instance of Show. One must make sure that the show functions does not examine the value, as descr is purely phantom. Here's an example of the good Label description:- data MyLabelDescr; instance Show MyLabelDescr where show _ = "descr"++ > data MyLabelDescr; instance Show MyLabelDescr where show _ = "descr"+ which obviously can be automated with Template Haskell. This model even allows the labels in a record to belong to different@@ -33,23 +36,23 @@ import Data.HList.Record (ShowLabel(..)) --- Labels are type-level naturals+-- | Labels are type-level naturals data Label x ns desc -- labels are exclusively type-level entities -- Public constructors for labels --- Construct the first label+-- | Construct the first label firstLabel :: ns -> desc -> Label HZero ns desc firstLabel = undefined --- Construct the next label+-- | Construct the next label nextLabel :: Label x ns desc -> desc' -> Label (HSucc x) ns desc' nextLabel = undefined --- Equality on labels (descriptions are ignored)+-- | Equality on labels (descriptions are ignored) instance ( HEq x x' b , TypeEq ns ns' b'@@ -58,7 +61,7 @@ => HEq (Label x ns desc) (Label x' ns' desc') b'' --- Show label+-- | Show label instance (HNat x, Show desc) => ShowLabel (Label x ns desc) where showLabel = show . getd
Data/HList/Label4.hs view
@@ -1,11 +1,14 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, EmptyDataDecls #-}-{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke Yet another model of labels.+ Labels are type proxies.++ See "Data.HList.MakeLabels" -} module Data.HList.Label4 where@@ -17,12 +20,12 @@ import Data.HList.Record --- Equality on labels+-- | Equality on labels instance TypeEq x y b => HEq (Proxy x) (Proxy y) b --- Show label+-- | Show label instance Typeable x => ShowLabel (Proxy x) where
Data/HList/Label5.hs view
@@ -1,13 +1,15 @@ {-# LANGUAGE FlexibleInstances, UndecidableInstances, MultiParamTypeClasses #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke Yet another model of labels.+ This model allow us to use any type as label type. As a result, we need some generic instances.+ Also, type errors may be more confusing now. -} @@ -19,12 +21,12 @@ import Data.HList.Record --- Equality on labels+-- | Equality on labels instance TypeEq x y b => HEq x y b --- Show label+-- | Show label instance Typeable x => ShowLabel x where
+ Data/HList/MakeLabels.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE TemplateHaskell, FlexibleInstances, EmptyDataDecls #-}+++{- | Making labels++ The following TH splice++> $(makeLabels ["getX","getY","draw"])++should expand into the following declarations++> data GetX; getX = proxy::Proxy GetX+> data GetY; getY = proxy::Proxy GetY+> data Draw; draw = proxy::Proxy Draw++-}++module Data.HList.MakeLabels (makeLabels,label) where++import Data.HList.FakePrelude++import Language.Haskell.TH.Ppr (pprint)+import Language.Haskell.TH.Syntax++import Data.Char (toUpper, toLower)+import Control.Monad (liftM)++capitalize, uncapitalize :: String -> String+capitalize (c:rest) = toUpper c : rest+uncapitalize (c:rest) = toLower c : rest+++-- Make the name of the type constructor whose string representation+-- is capitalized str+make_tname str = mkName $ capitalize str++-- Make the name of the value identifier whose string representation+-- is uncapitalized str+make_dname str = mkName $ uncapitalize str++-- The template of our declaration. We will then replace all occurences+-- of Foo with the desired name+dcl_template = [d| data Foo; foo = proxy::Proxy Foo |]++-- A very dirty traversal/replacement...++class ReplaceSyntax a where+ replace_name :: (Name,Name) -> (Name,Name) -> a -> a++instance ReplaceSyntax [Dec] where+ replace_name frm to dcls = map (replace_name frm to) dcls++instance ReplaceSyntax Dec where+ replace_name (tfrom,dfrom) (tto,dto)+ dcl@(DataD ctx n parms con othern) =+ if tfrom == n then+ DataD ctx tto parms con othern+ else dcl+ replace_name (tfrom,dfrom) (tto,dto)+ dcl@(ValD (VarP n) (NormalB body) []) =+ let n' = if n == dfrom then dto else n+ in ValD (VarP n')+ (NormalB (replace_name (tfrom,dfrom) (tto,dto) body)) []++ replace_name (tfrom,dfrom) (tto,dto) dcl =+ error $ "Can't handle: " ++ show dcl+++instance ReplaceSyntax Exp where+ replace_name from to (SigE exp tp) =+ SigE (replace_name from to exp)+ (replace_name from to tp)+ replace_name from to exp = exp+++instance ReplaceSyntax Type where+ replace_name (tfrom,dfrom) (tto,dto) tp@(ConT n) =+ if n == tfrom then (ConT tto) else tp+ replace_name from to (AppT t1 t2) =+ (AppT (replace_name from to t1) (replace_name from to t2))++-- | Our main function+makeLabels :: [String] -> Q [Dec]+makeLabels = liftM concat . sequence . map repl+ where+ repl n = liftM (replace_name from (to n)) dcl_template+ from = (make_tname "foo",make_dname "foo")+ to n = (make_tname n,make_dname n)++-- | Make a single label+label :: String -> Q [Dec]+label s = makeLabels [s]++-- Show the code expression+show_code cde = runQ cde >>= putStrLn . pprint++{-+t1 = show_code [d| data Foo |]++t2 = showName $ mkName "Foo"++t3 = show_code $+ liftM (replace_name+ (make_tname "foo",make_dname "foo")+ (make_tname "bar",make_dname "bar")) dcl_template+-}++t4 = show_code $ makeLabels ["getX","getY","draw"]
Data/HList/Record.hs view
@@ -2,7 +2,7 @@ FlexibleContexts, UndecidableInstances, ScopedTypeVariables #-} {-# OPTIONS_GHC -fno-warn-missing-signatures #-} -{-+{- | The HList library (C) 2004-2006, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -10,11 +10,104 @@ Extensible records The are different models of labels that go with this module;- see the files Label?.hs.+ see:++ * "Data.HList.Label1"++ * "Data.HList.Label2"++ * "Data.HList.Label3"++ * "Data.HList.Label4"++ * "Data.HList.Label5" -} -module Data.HList.Record where+module Data.HList.Record+(+ -- * Records + -- ** Labels+ -- $labels+ LVPair(..),+ labelLVPair,+ newLVPair,++ -- ** Record+ Record(..),+ mkRecord,+ emptyRecord,++ -- *** Getting Labels+ RecordLabels,+ recordLabels,+ recordLabels',++ -- *** Getting Values+ RecordValues(..),+ recordValues,++ -- * Operations+ -- ** Show+ -- | A corresponding 'Show' instance exists as+ --+ -- > show x = "Record {" ++ showComponents "" x ++ "}"+ ShowComponents(..),+ ShowLabel(..),++ -- ** Lookup+ HasField(..),+ HasField'(..),++ -- ** Delete+ -- | 'hDeleteAtLabel' @label record@+ hDeleteAtLabel,++ -- ** Update+ -- | 'hUpdateAtLabel' @label value record@+ hUpdateAtLabel,+ hTPupdateAtLabel,++ -- ** Rename Label+ hRenameLabel,++ -- ** Projection+ -- $projection+ hProjectByLabels,+ hProjectByLabels2,++ -- ** Unions+ -- *** Left+ HLeftUnion(hLeftUnion),+ HLeftUnionBool(hLeftUnionBool),++ -- *** Symmetric+ -- $symmetricUnion+ UnionSymRec(unionSR),++ -- ** Reorder Labels+ hRearrange,++ -- ** Extension+ -- | 'hExtend', 'hAppend'++ -- * Unclassified+ -- | Probably internals, that may not be useful+ DuplicatedLabel(..),+ ExtraField(..),+ FieldNotFound(..),+ H2ProjectByLabels(h2projectByLabels),+ H2ProjectByLabels'(h2projectByLabels'),+ HLabelSet,+ HLabelSet',+ HRLabelSet,+ HRLabelSet',+ HRearrange(hRearrange2),+ HRearrange'(hRearrange2'),+ UnionSymRec'(..)+) where++ import Data.HList.FakePrelude import Data.HList.HListPrelude import Data.HList.HArray@@ -22,16 +115,16 @@ {-----------------------------------------------------------------------------} --- Record types as label-value pairs, where label is purely phantom.+-- $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. --- Field of label l with value type v+-- | Field of label l with value type v newtype LVPair l v = LVPair { valueLVPair :: v } deriving Eq --- Label accessor+-- | Label accessor labelLVPair :: LVPair l v -> l labelLVPair = undefined @@ -41,17 +134,17 @@ newtype Record r = Record r deriving Eq --- Build a record+-- | Build a record mkRecord :: HRLabelSet r => r -> Record r mkRecord = Record --- Build an empty record+-- | Build an empty record emptyRecord :: Record HNil emptyRecord = mkRecord HNil --- Propery of a proper label set for a record: no duplication of labels+-- | Propery of a proper label set for a record: no duplication of labels class HRLabelSet ps instance HRLabelSet HNil@@ -80,7 +173,8 @@ data DuplicatedLabel l = DuplicatedLabel l instance Fail (DuplicatedLabel x) => HLabelSet' x ls HTrue --- Construct the (phantom) list of labels of the record.+-- | Construct the (phantom) list of labels of the record.+-- -- This is a purely type-level function. class RecordLabels r ls | r -> ls instance RecordLabels HNil HNil@@ -93,7 +187,7 @@ recordLabels :: RecordLabels r ls => Record r -> ls recordLabels (Record r) = recordLabels' r --- Construct the list of values of the record.+-- | Construct the list of values of the record. class RecordValues r ls | r -> ls where recordValues' :: r -> ls instance RecordValues HNil HNil@@ -109,7 +203,7 @@ {-----------------------------------------------------------------------------} --- A Show instance to appeal to normal records+-- 'Show' instance to appeal to normal records instance ShowComponents r => Show (Record r) where@@ -145,7 +239,7 @@ {-----------------------------------------------------------------------------} --- Extension for records+-- Extension instance HRLabelSet (HCons (LVPair l v) r) => HExtend (LVPair l v) (Record r) (Record (HCons (LVPair l v) r))@@ -155,7 +249,7 @@ {-----------------------------------------------------------------------------} --- Record concatenation+-- Concatenation instance ( HRLabelSet r'' , HAppend r r' r''@@ -167,11 +261,15 @@ {-----------------------------------------------------------------------------} --- Lookup operation-+-- Lookup+--+-- | -- 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 class HasField l r v | l r -> v where hLookupByLabel:: l -> r -> v@@ -191,9 +289,6 @@ -} --- 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 instance HasField l r v => HasField l (Record r) v where hLookupByLabel l (Record r) = hLookupByLabel l r@@ -215,7 +310,9 @@ {-----------------------------------------------------------------------------} --- Delete operation+-- Delete++hDeleteAtLabel :: (H2ProjectByLabels (HCons e HNil) t t1 t2) =>e -> Record t -> Record t2 hDeleteAtLabel l (Record r) = Record r' where (_,r') = h2projectByLabels (HCons l HNil) r@@ -223,7 +320,9 @@ {-----------------------------------------------------------------------------} --- Update operation+-- Update++hUpdateAtLabel :: (HUpdateAtHNat n (LVPair l v) t l',HFind l ls n,RecordLabels t ls) =>l -> v -> Record t -> Record l' hUpdateAtLabel l v (Record r) = Record r' where n = hFind l (recordLabels' r)@@ -231,17 +330,27 @@ {-----------------------------------------------------------------------------}--- Projection for records+-- Projection++-- $projection -- It is also an important operation: the basis of many -- deconstructors -- so we try to implement it efficiently.+++-- | @hProjectByLabels ls r@ returns @r@ with only the labels in @ls@ remaining hProjectByLabels :: (HRLabelSet a, H2ProjectByLabels ls t a b) => ls -> Record t -> Record a hProjectByLabels ls (Record r) = mkRecord (fst $ h2projectByLabels ls r) +-- | See 'H2ProjectByLabels'+hProjectByLabels2 :: (H2ProjectByLabels ls t t1 t2, HRLabelSet t1, HRLabelSet t2) =>ls -> Record t -> (Record t1, Record t2) hProjectByLabels2 ls (Record r) = (mkRecord rin, mkRecord rout) where (rin,rout) = h2projectByLabels ls r --- Invariant: r = rin `disjoint-union` rout--- labels(rin) = ls+-- | /Invariant/:+--+-- > r === rin `disjoint-union` rout+-- > labels rin === ls+-- > where (rin,rout) = hProjectByLabels ls r class H2ProjectByLabels ls r rin rout | ls r -> rin rout where h2projectByLabels :: ls -> r -> (rin,rout) @@ -275,7 +384,9 @@ {-----------------------------------------------------------------------------} --- Rename the label of record+-- | Rename the label of record+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) hRenameLabel l l' r = r'' where v = hLookupByLabel l r@@ -285,28 +396,29 @@ {-----------------------------------------------------------------------------} --- A variation on update: type-preserving update.+-- | A variation on 'hUpdateAtLabel': type-preserving update.+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' hTPupdateAtLabel l v r = hUpdateAtLabel l v r where te :: a -> a -> () te _ _ = () _ = te v (hLookupByLabel l r) -{-+{- ^ --- We could also say:+We could also say: -hTPupdateAtLabel l v r = hUpdateAtLabel l v r `asTypeOf` r+> 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.+Then we were taking a dependency on Haskell's type equivalence.+This would also constrain the actual implementation of hUpdateAtLabel. -} {-----------------------------------------------------------------------------} --- Subtyping for records-+-- | Subtyping for records instance ( RecordLabels r' ls , H2ProjectByLabels ls r r' rout )@@ -315,6 +427,8 @@ {-----------------------------------------------------------------------------} +-- Left Union+ class HLeftUnion r r' r'' | r r' -> r'' where hLeftUnion :: r -> r' -> r'' @@ -345,23 +459,30 @@ {-----------------------------------------------------------------------------}+-- $symmetricUnion -- 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+--+-- 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+--+-- > 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.+--+--+-- 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+--+-- 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@@ -382,8 +503,9 @@ class UnionSymRec' b r1 f2 r2' ru | b r1 f2 r2' -> ru where unionSR' :: b -> r1 -> f2 -> r2' -> (ru, ru) --- Field f2 is already in r1, so it will be in the union of r1+-- | 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 instance (UnionSymRec r1 r2' (Record ru),@@ -406,13 +528,13 @@ ur' = hExtend f2 ur {-----------------------------------------------------------------------------}--- Rearranges a record by labels. Returns the record r, rearranged such that+-- | 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. hRearrange :: (HLabelSet ls, HRearrange ls r r') => ls -> Record r -> Record r' hRearrange ls (Record r) = Record $ hRearrange2 ls r --- Helper class for hRearrange+-- | Helper class for 'hRearrange' class HRearrange ls r r' | ls r -> r' where hRearrange2 :: ls -> r -> r' @@ -425,7 +547,7 @@ hRearrange2 ~(HCons l ls) r = hRearrange2' l ls rin rout where (rin, rout) = h2projectByLabels (HCons l HNil) r --- Helper class 2 for hRearrange+-- | Helper class 2 for 'hRearrange' class HRearrange' l ls rin rout r' | l ls rin rout -> r' where hRearrange2' :: l -> ls -> rin -> rout -> r' instance HRearrange ls rout r' =>@@ -435,9 +557,12 @@ data ExtraField l = ExtraField data FieldNotFound l = FieldNotFound +-- | For improved error messages instance Fail (FieldNotFound l) => HRearrange' l ls HNil rout (FieldNotFound l) where hRearrange2' _ _ _ _ = FieldNotFound++-- | For improved error messages instance Fail (ExtraField l) => HRearrange HNil (HCons (LVPair l v) a) (ExtraField l) where hRearrange2 _ _ = ExtraField
Data/HList/RecordP.hs view
@@ -2,13 +2,14 @@ UndecidableInstances, FlexibleInstances #-} {-# OPTIONS -fglasgow-exts #-} -{-+{- | The HList library (C) 2004-2006, Oleg Kiselyov, Ralf Laemmel, Keean Schupke Extensible records: labels are phantom, so at run-time, the record is just a heterogenous list of field values.+ This sort of record is generalizable to `tables' (which are, at run-time, a list or a map containing the heterogenous lists of field values).
Data/HList/TIC.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE FlexibleInstances, FlexibleContexts #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -20,14 +20,14 @@ {-----------------------------------------------------------------------------} --- A datatype for type-indexed co-products+-- | A datatype for type-indexed co-products data TIC l = TIC Dynamic {-----------------------------------------------------------------------------} --- Public constructor+-- | Public constructor mkTIC :: ( HTypeIndexed l , HTypeProxied l@@ -41,7 +41,7 @@ {-----------------------------------------------------------------------------} --- Public destructor+-- | Public destructor unTIC :: ( HTypeIndexed l , HTypeProxied l@@ -55,7 +55,7 @@ {-----------------------------------------------------------------------------} --- A type-indexed type sequence that is a sequence of proxy types+-- | A type-indexed type sequence that is a sequence of proxy types class HTypeProxied l instance HTypeProxied HNil@@ -64,7 +64,7 @@ {-----------------------------------------------------------------------------} --- TICs are opaque+-- | TICs are opaque instance Show (TIC l) where
Data/HList/TIP.hs view
@@ -2,9 +2,7 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, FlexibleContexts #-} -module Data.HList.TIP where--{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -12,6 +10,9 @@ Type-indexed products. -} +module Data.HList.TIP where++ import Data.HList.FakePrelude import Data.HList.HListPrelude import Data.HList.HArray@@ -21,7 +22,7 @@ {-----------------------------------------------------------------------------} --- The newtype for type-indexed products+-- | The newtype for type-indexed products newtype TIP l = TIP l deriving (Read,Show)@@ -39,7 +40,7 @@ {-----------------------------------------------------------------------------} --- Type-indexed type sequences+-- | Type-indexed type sequences class HList l => HTypeIndexed l instance HTypeIndexed HNil@@ -75,12 +76,14 @@ {-----------------------------------------------------------------------------} --- Type-indexed extension+-- | Type-indexed extension+-- -- signature is inferred--- hExtend' :: (HTypeIndexed t, HOccursNot e t) => e -> TIP t -> TIP (HCons e t)+--+-- > hExtend' :: (HTypeIndexed t, HOccursNot e t) => e -> TIP t -> TIP (HCons e t) hExtend' e (TIP l) = mkTIP (HCons e l) -{-+{- $example Valid type I @@ -148,7 +151,7 @@ {-----------------------------------------------------------------------------} --- Shielding type-indexed operations+-- | Shielding type-indexed operations -- The absence of signatures is deliberate! They all must be inferred. onTIP f (TIP l) = mkTIP (f l)@@ -175,56 +178,60 @@ {-----------------------------------------------------------------------------} --- Sample code+-- * Sample code -{-+{- $sampleCode Assume -myTipyCow = TIP myAnimal+> myTipyCow = TIP myAnimal -animalKey :: (HOccurs Key l, SubType l (TIP Animal)) => l -> Key-animalKey = hOccurs+> animalKey :: (HOccurs Key l, SubType l (TIP Animal)) => l -> Key+> animalKey = hOccurs Session log -*TIP> :t myTipyCow-myTipyCow :: TIP Animal+> *TIP> :t myTipyCow+> myTipyCow :: TIP Animal -*TIP> hOccurs myTipyCow :: Breed-Cow+> *TIP> hOccurs myTipyCow :: Breed+> Cow -*TIP> hExtend BSE myTipyCow-TIP (HCons BSE- (HCons (Key 42)- (HCons (Name "Angus")- (HCons Cow- (HCons (Price 75.5)- HNil)))))+> *TIP> hExtend BSE myTipyCow+> TIP (HCons BSE+> (HCons (Key 42)+> (HCons (Name "Angus")+> (HCons Cow+> (HCons (Price 75.5)+> HNil))))) -*TIP> BSE .*. myTipyCow---- same as before ---+> *TIP> BSE .*. myTipyCow+> --- same as before --- -*TIP> Sheep .*. myTipyCow-Type error ...+> *TIP> Sheep .*. myTipyCow+> Type error ... -*TIP> Sheep .*. tipyDelete myTipyCow (HProxy::HProxy Breed)-TIP (HCons Sheep (HCons (Key 42) (HCons (Name "Angus") (HCons (Price 75.5) HNil))))+> *TIP> Sheep .*. tipyDelete myTipyCow (HProxy::HProxy Breed)+>TIP (HCons Sheep (HCons (Key 42) (HCons (Name "Angus") (HCons (Price 75.5) HNil)))) -*TIP> tipyUpdate myTipyCow Sheep-TIP (HCons (Key 42) (HCons (Name "Angus") (HCons Sheep (HCons (Price 75.5) HNil))))+> *TIP> tipyUpdate myTipyCow Sheep+> TIP (HCons (Key 42) (HCons (Name "Angus") (HCons Sheep (HCons (Price 75.5) HNil)))) -} {-----------------------------------------------------------------------------} +-- * Sample 2++-- | -- This example from the TIR paper challenges singleton lists. -- Thanks to the HW 2004 reviewer who pointed out the value of this example. -- We note that the explicit type below is richer than the inferred type. -- This richer type is needed for making this operation more polymorphic.--- That is, a) would not work without the explicit type, while it would:--- a) ((+) (1::Int)) $ snd $ tuple oneTrue--- b) ((+) (1::Int)) $ fst $ tuple oneTrue+-- That is, /a)/ would not work without the explicit type, while it would:+--+-- > a) ((+) (1::Int)) $ snd $ tuple oneTrue+-- > b) ((+) (1::Int)) $ fst $ tuple oneTrue tuple :: ( HOccurs e1 (TIP l) , HType2HNat e1 l n@@ -244,7 +251,7 @@ in (x,y) --- A specific tuple+-- | A specific tuple oneTrue :: TIP (HCons Int (HCons Bool HNil)) oneTrue = hExtend (1::Int) (hExtend True emptyTIP)
Data/HList/TypeCastGeneric1.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke
Data/HList/TypeCastGeneric2.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances #-}-{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -7,7 +7,8 @@ A generic implementation of a type-safe cast. The specific coding here is only shown for completeness' sake and it is explained in the TR version of the paper. The shown coding does not rely on separate- compilation (while TypeCastGeneric1.hs does), but on some other tricks.+ compilation (while "Data.HList.TypeCastGeneric1" does), but on some other+ tricks. -} module Data.HList.TypeCastGeneric2 where
Data/HList/TypeEqBoolGeneric.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FlexibleContexts #-}-{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke
Data/HList/TypeEqGeneric1.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, FlexibleContexts, OverlappingInstances, UndecidableInstances #-}-{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -15,7 +15,7 @@ and by transitive closure therefore relies on separate compilation of TypeCast clients and the TypeCast instance. - There is another encoding in TypeEqGeneric2.hs.+ There is another encoding in "Data.Hlist.TypeEqGeneric2". -} module Data.HList.TypeEqGeneric1 where
Data/HList/TypeEqGeneric2.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts, FlexibleInstances, UndecidableInstances, OverlappingInstances #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -8,7 +8,7 @@ A generic implementation of a type equality predicate. The given implementation only works for GHC. The specific coding here is only shown for completeness' sake. We actually favour the encoding from- TypeEqGeneric1.hs for its conciseness. The specific coding here+ "Data.Hlist.TypeEqGeneric1" for its conciseness. The specific coding here does not rely on separate compilation (while TypeEqGeneric1.hs does), but on some other tricks. -}
Data/HList/Variant.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances, FlexibleContexts #-} -{-+{- | The HList library (C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke@@ -29,14 +29,14 @@ {-----------------------------------------------------------------------------} --- Variant types on the basis of label-maybe pairs.+-- | Variant types on the basis of label-maybe pairs. newtype Variant mr = Variant mr {-----------------------------------------------------------------------------} --- Turn proxy sequence into sequence of Nothings+-- | Turn proxy sequence into sequence of Nothings class HMaybied r r' | r -> r' where@@ -54,7 +54,7 @@ {-----------------------------------------------------------------------------} --- Public constructor+-- | Public constructor mkVariant :: ( RecordLabels v ls , HFind x ls n@@ -72,7 +72,7 @@ {-----------------------------------------------------------------------------} --- Public destructor+-- | Public destructor unVariant :: ( RecordLabels v ls , HFind x ls n@@ -88,7 +88,7 @@ {-----------------------------------------------------------------------------} --- Variants are opaque+-- | Variants are opaque instance Show (Variant v) where
HList.cabal view
@@ -1,5 +1,5 @@ Name: HList-Version: 0.2.1+Version: 0.2.2 Category: Data Synopsis: Heterogeneous lists Description: HList is a record system providing strongly typed heterogenous lists, records,@@ -13,7 +13,7 @@ Data-files: README Cabal-version: >= 1.4 Tested-With: GHC==6.8.2-Build-Depends: base >= 3 && < 5+Build-Depends: base >= 3 && < 5, template-haskell Build-Type: Simple Exposed-modules: Data.HList, Data.HList.CommonMain, Data.HList.Variant, Data.HList.GhcSyntax, Data.HList.GhcRecord, Data.HList.Record, Data.HList.HZip, Data.HList.TIC, Data.HList.TIP,@@ -21,7 +21,9 @@ Data.HList.HListPrelude, Data.HList.TypeEqBoolGeneric, Data.HList.TypeEqGeneric1, Data.HList.TypeCastGeneric1, Data.HList.TypeCastGeneric2, Data.HList.FakePrelude, Data.HList.RecordP, Data.HList.TypeEqGeneric2,- Data.HList.Label1, Data.HList.Label2, Data.HList.Label3, Data.HList.Label4, Data.HList.Label5+ Data.HList.Label1, Data.HList.Label2, Data.HList.Label3, Data.HList.Label4, Data.HList.Label5,++ Data.HList.MakeLabels extensions: EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses, OverlappingInstances, ScopedTypeVariables, RankNTypes,
README view
@@ -1,21 +1,26 @@ (C) 2004--2010, Oleg Kiselyov, Ralf Laemmel, Keean Schupke +Contributors:+ Justin Bailey, Brian Bloniarz, Gwern Branwen, Einar Karttunen,+ and Adam Vogt++ The HList library and samples ---------------------------------------------------------------------- Getting the code -> darcs get http://darcs.haskell.org/HList+> darcs get http://code.haskell.org/HList ---------------------------------------------------------------------- Pushing changes -You need an account at darcs.haskell.org+You need an account at code.haskell.org > cd HList-> darcs pull user@darcs.haskell.org:/srv/darcs/HList+> darcs pull user@code.haskell.org:/srv/darcs/HList > darcs record > darcs push @@ -29,11 +34,12 @@ You can get HList from Hackage or from Darcs: -$ darcs get --partial http://darcs.haskell.org/HList/+$ darcs get --partial http://code.haskell.org/HList/ The code works --- within the limits exercised in the source files --- for both GHC (6.4) and Hugs (Nov 2003). See the examples/Makefile for ways of running test cases.+The last GHC version tried: GHC 6.12 One may run "cd examples; make test" to check the distribution.