on main help sign in
Update documentation and module structure (#38)
2df2fcdVladislav Zavialov
README.md+16−14
@@ -4,36 +4,38 @@
4[![Build status](https://secure.travis-ci.org/kowainik/typerep-map.svg)](https://travis-ci.org/kowainik/typerep-map)
4[![Build status](https://secure.travis-ci.org/kowainik/typerep-map.svg)](https://travis-ci.org/kowainik/typerep-map)
5[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/vrom911/typerep-map/blob/master/LICENSE)
5[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/vrom911/typerep-map/blob/master/LICENSE)
6
6
7−`typerep-map` introduces `TypeRepMap` — data structure like [`Map`](http://hackage.haskell.org/package/containers-0.6.0.1/docs/Data-Map-Lazy.html#t:Map), but where types serve as keys, and values have the types specified in the corresponding key spots.
7+`typerep-map` introduces `TMap` and `TypeRepMap` — data structures like [`Map`](http://hackage.haskell.org/package/containers-0.6.0.1/docs/Data-Map-Lazy.html#t:Map), but where types serve as keys, and values have the types specified in the corresponding key spots.
8
8
9## Usage example
9## Usage example
10
10
11```haskell
11```haskell
12−ghci> let typeRepMap = insert (Identity True) $ one (Identity (42 :: Int))
12+ghci> import Data.TMap
13
13
14−ghci> size typeRepMap
14+ghci> tm = insert True $ one (42 :: Int)
15+
16+ghci> size tm
152
172
16
18
17−ghci> let res = lookup typeRepMap
19+ghci> res = lookup tm
18
20
19−ghci> res :: Maybe (Identity Int)
21+ghci> res :: Maybe Int
20−Just (Identity 42)
22+Just 42
21
23
22−ghci> res :: Maybe (Identity Bool)
24+ghci> res :: Maybe Bool
23−Just (Identity True)
25+Just True
24
26
25−ghci> res :: Maybe (Identity String)
27+ghci> res :: Maybe String
26Nothing
28Nothing
27
29
28−ghci> lookup (insert (Identity "hello") typeRepMap) :: Maybe (Identity String)
30+ghci> lookup (insert "hello" tm) :: Maybe String
29−Just (Identity "hello")
31+Just "hello"
30
32
31−ghci> member @Int typeRepMap
33+ghci> member @Int tm
32True
34True
33
35
34−ghci> let trMap = delete @Int typeRepMap
36+ghci> tm' = delete @Int tm
35
37
36−ghci> member @Int trMap
38+ghci> member @Int tm'
37False
39False
38```
40```
39
41
benchmark/CacheMap.hs+1−1
@@ -21,7 +21,7 @@ import Data.Proxy (Proxy (..))
21import Data.Typeable (Typeable)
21import Data.Typeable (Typeable)
22import GHC.TypeLits
22import GHC.TypeLits
23
23
24−import Data.TypeRep.Map (TF (..), TypeRepMap (..), fromList, lookup)
24+import Data.TypeRepMap.Internal (TF (..), TypeRepMap (..), fromList, lookup)
25
25
26benchCacheMap :: Benchmark
26benchCacheMap :: Benchmark
27benchCacheMap = bgroup "vector optimal cache"
27benchCacheMap = bgroup "vector optimal cache"
src/Data/TMap.hsnew file+148
@@ -0,0 +1,148 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE Rank2Types #-}
3+
4+{- |
5+'TMap' is a heterogeneous data structure similar in its essence to
6+'Data.Map.Map' with types as keys, where each value has the type of its key.
7+
8+Here is an example of a 'TMap' with a comparison to 'Data.Map.Map':
9+
10+@
11+ 'Data.Map.Map' 'Prelude.String' 'Prelude.String' 'TMap'
12+-------------------- -----------------
13+ \"Int\" -> \"5\" 'Prelude.Int' -> 5
14+ \"Bool\" -> \"True\" 'Prelude.Bool' -> 'Prelude.True'
15+ \"Char\" -> \"\'x\'\" 'Prelude.Char' -> \'x\'
16+@
17+
18+The runtime representation of 'TMap' is an array, not a tree. This makes
19+'lookup' significantly more efficient.
20+
21+-}
22+
23+module Data.TMap
24+ ( -- * Map type
25+ TMap
26+
27+ -- * Construction
28+ , empty
29+ , one
30+
31+ -- * Modification
32+ , insert
33+ , delete
34+ , unionWith
35+ , union
36+
37+ -- * Query
38+ , lookup
39+ , member
40+ , size
41+ ) where
42+
43+import Prelude hiding (lookup)
44+
45+import Data.Functor.Identity (Identity (..))
46+import Data.Typeable (Typeable)
47+import GHC.Exts (coerce)
48+
49+import qualified Data.TypeRepMap as F
50+
51+-- | 'TMap' is a special case of 'F.TypeRepMap' when the interpretation is
52+-- 'Identity'.
53+type TMap = F.TypeRepMap Identity
54+
55+{- |
56+
57+A 'TMap' with no values stored in it.
58+
59+prop> size empty == 0
60+prop> member @a empty == False
61+
62+-}
63+empty :: TMap
64+empty = F.empty
65+{-# INLINE empty #-}
66+
67+{- |
68+
69+Construct a 'TMap' with a single element.
70+
71+prop> size (one x) == 1
72+prop> member @a (one (x :: a)) == True
73+
74+-}
75+one :: forall a . Typeable a => a -> TMap
76+one x = coerce (F.one @a @Identity $ coerce x)
77+{-# INLINE one #-}
78+
79+{- |
80+
81+Insert a value into a 'TMap'.
82+
83+prop> size (insert v tm) >= size tm
84+prop> member @a (insert (x :: a) tm) == True
85+
86+-}
87+insert :: forall a . Typeable a => a -> TMap -> TMap
88+insert x = coerce (F.insert @a @Identity $ coerce x)
89+{-# INLINE insert #-}
90+
91+{- | Delete a value from a 'TMap'.
92+
93+prop> size (delete @a tm) <= size tm
94+prop> member @a (delete @a tm) == False
95+
96+>>> tm = delete @Bool $ insert True $ one 'a'
97+>>> size tm
98+1
99+>>> member @Bool tm
100+False
101+>>> member @Char tm
102+True
103+-}
104+delete :: forall a . Typeable a => TMap -> TMap
105+delete = F.delete @a @Identity
106+{-# INLINE delete #-}
107+
108+-- | The union of two 'TMap's using a combining function.
109+unionWith :: (forall x. x -> x -> x) -> TMap -> TMap -> TMap
110+unionWith f = F.unionWith fId
111+ where
112+ fId :: forall y . Identity y -> Identity y -> Identity y
113+ fId y1 y2 = Identity $ f (coerce y1) (coerce y2)
114+{-# INLINE unionWith #-}
115+
116+-- | The (left-biased) union of two 'TMap's. It prefers the first map when
117+-- duplicate keys are encountered, i.e. @'union' == 'unionWith' const@.
118+union :: TMap -> TMap -> TMap
119+union = F.union
120+{-# INLINE union #-}
121+
122+{- | Lookup a value of the given type in a 'TMap'.
123+
124+>>> x = lookup $ insert (11 :: Int) empty
125+>>> x :: Maybe Int
126+Just 11
127+>>> x :: Maybe ()
128+Nothing
129+-}
130+lookup :: forall a. Typeable a => TMap -> Maybe a
131+lookup = coerce (F.lookup @a @Identity)
132+{-# INLINE lookup #-}
133+
134+{- | Check if a value of the given type is present in a 'TMap'.
135+
136+>>> member @Char $ one 'a'
137+True
138+>>> member @Bool $ one 'a'
139+False
140+-}
141+member :: forall a . Typeable a => TMap -> Bool
142+member = F.member @a @Identity
143+{-# INLINE member #-}
144+
145+-- | Get the amount of elements in a 'TMap'.
146+size :: TMap -> Int
147+size = F.size
148+{-# INLINE size #-}
src/Data/TypeRep/TMap.hsdeleted−89
@@ -1,89 +0,0 @@
1−{-# LANGUAGE AllowAmbiguousTypes #-}
2−{-# LANGUAGE Rank2Types #-}
3−
4−-- | This module introduces 'TMap' data type — 'TR.TypeRepMap' parametrized by 'Identity'.
5−
6−module Data.TypeRep.TMap
7− ( -- * Map type
8− TMap
9−
10− -- * Construction
11− , empty
12− , one
13−
14− -- * Modification
15− , insert
16− , delete
17− , hoist
18− , unionWith
19− , union
20−
21− -- * Query
22− , lookup
23− , member
24− , size
25− ) where
26−
27−import Prelude hiding (lookup)
28−
29−import Data.Functor.Identity (Identity (..))
30−import Data.Typeable (Typeable)
31−import GHC.Exts (coerce)
32−
33−import qualified Data.TypeRep.Map as TR
34−
35−-- | 'TR.TypeRepMap' parametrized by 'Identity'.
36−type TMap = TR.TypeRepMap Identity
37−
38−-- | Similar to 'TR.empty' but for 'TMap'.
39−empty :: TMap
40−empty = TR.empty
41−{-# INLINE empty #-}
42−
43−-- | Similar to 'TR.one' but for 'TMap'.
44−one :: forall a . Typeable a => a -> TMap
45−one x = coerce (TR.one @a @Identity $ coerce x)
46−{-# INLINE one #-}
47−
48−-- | Similar to 'TR.insert' but for 'TMap'.
49−insert :: forall a . Typeable a => a -> TMap -> TMap
50−insert x = coerce (TR.insert @a @Identity $ coerce x)
51−{-# INLINE insert #-}
52−
53−-- | Similar to 'TR.delete' but for 'TMap'.
54−delete :: forall a . Typeable a => TMap -> TMap
55−delete = TR.delete @a @Identity
56−{-# INLINE delete #-}
57−
58−-- | Similar to 'TR.hoist' but for 'TMap'.
59−hoist :: (forall x. x -> g x) -> TMap -> TR.TypeRepMap g
60−hoist f = TR.hoist (f . coerce)
61−{-# INLINE hoist #-}
62−
63−-- | Similar to 'TR.unionWith' but for 'TMap'.
64−unionWith :: (forall x. x -> x -> x) -> TMap -> TMap -> TMap
65−unionWith f = TR.unionWith fId
66− where
67− fId :: forall y . Identity y -> Identity y -> Identity y
68− fId y1 y2 = Identity $ f (coerce y1) (coerce y2)
69−{-# INLINE unionWith #-}
70−
71−-- | Similar to 'TR.union' but for 'TMap'.
72−union :: TMap -> TMap -> TMap
73−union = TR.union
74−{-# INLINE union #-}
75−
76−-- | Similar to 'TR.lookup' but for 'TMap'.
77−lookup :: forall a. Typeable a => TMap -> Maybe a
78−lookup = coerce (TR.lookup @a @Identity)
79−{-# INLINE lookup #-}
80−
81−-- | Similar to 'TR.member' but for 'TMap'.
82−member :: forall a . Typeable a => TMap -> Bool
83−member = TR.member @a @Identity
84−{-# INLINE member #-}
85−
86−-- | Similar to 'TR.size' but for 'TMap'.
87−size :: TMap -> Int
88−size = TR.size
89−{-# INLINE size #-}
src/Data/TypeRepMap.hsnew file+65
@@ -0,0 +1,65 @@
1+{-# LANGUAGE NoImplicitPrelude #-}
2+
3+-- | A version of 'Data.TMap.TMap' parametrized by an interpretation @f@. This
4+-- sort of parametrization may be familiar to users of @vinyl@ records.
5+--
6+-- @'TypeRepMap' f@ is a more efficient replacement for @DMap
7+-- 'Type.Reflection.TypeRep' f@ (where @DMap@ is from the @dependent-map@
8+-- package).
9+--
10+-- Here is an example of using 'Prelude.Maybe' as an interpretation, with a
11+-- comparison to 'Data.TMap.TMap':
12+--
13+-- @
14+-- 'Data.TMap.TMap' 'TypeRepMap' 'Prelude.Maybe'
15+-- -------------- -------------------
16+-- Int -> 5 Int -> Just 5
17+-- Bool -> True Bool -> Nothing
18+-- Char -> \'x\' Char -> Just \'x\'
19+-- @
20+--
21+-- In fact, a 'Data.TMap.TMap' is defined as 'TypeRepMap'
22+-- 'Data.Functor.Identity'.
23+--
24+-- Since 'Type.Reflection.TypeRep' is poly-kinded, the interpretation can use
25+-- any kind for the keys. For instance, we can use the 'GHC.TypeLits.Symbol'
26+-- kind to use 'TypeRepMap' as an extensible record:
27+--
28+-- @
29+-- newtype Field name = F (FType name)
30+--
31+-- type family FType (name :: Symbol) :: Type
32+-- type instance FType "radius" = Double
33+-- type instance FType "border-color" = RGB
34+-- type instance FType "border-width" = Double
35+--
36+-- 'TypeRepMap' Field
37+-- --------------------------------------
38+-- "radius" -> F 5.7
39+-- "border-color" -> F (rgb 148 0 211)
40+-- "border-width" -> F 0.5
41+-- @
42+--
43+module Data.TypeRepMap
44+ ( -- * Map type
45+ TypeRepMap()
46+
47+ -- * Construction
48+ , empty
49+ , one
50+
51+ -- * Modification
52+ , insert
53+ , delete
54+ , hoist
55+ , unionWith
56+ , union
57+
58+ -- * Query
59+ , lookup
60+ , member
61+ , size
62+
63+ ) where
64+
65+import Data.TypeRepMap.Internal
src/Data/TypeRep/Map.hs → src/Data/TypeRepMap/Internal.hsrenamed+83−56
@@ -12,33 +12,13 @@
12
12
13-- {-# OPTIONS_GHC -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes #-}
13-- {-# OPTIONS_GHC -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes #-}
14
14
15−-- | This module introduces the 'TypeRepMap' data structure and functions to work with it.
15+-- | Internal API for 'TypeRepMap' and operations on it. The functions here do
16−
16+-- not have any stability guarantees and can change between minor versions.
17−module Data.TypeRep.Map
17+--
18− ( -- * Map type
18+-- If you need to use this module for purposes other than tests,
19+-- create an issue.
20+--
19− TypeRepMap (..)
21+module Data.TypeRepMap.Internal where
20−
21− -- * Construction
22− , empty
23− , one
24−
25− -- * Modification
26− , insert
27− , delete
28− , hoist
29− , unionWith
30− , union
31−
32− -- * Query
33− , lookup
34− , member
35− , size
36−
37− -- * Helpful testing functions
38− , TF (..)
39− , fromList
40− , toFingerprints
41− ) where
42
22
43import Prelude hiding (lookup)
23import Prelude hiding (lookup)
44
24
@@ -64,12 +44,34 @@ import qualified Data.IntMap.Strict as IM
64import qualified Data.Map.Strict as Map
44import qualified Data.Map.Strict as Map
65import qualified GHC.Exts as GHC (fromList, toList)
45import qualified GHC.Exts as GHC (fromList, toList)
66
46
67−-- | Map-like data structure that keeps types as keys.
47+{- |
48+
49+'TypeRepMap' is a heterogeneous data structure similar in its essence to
50+'Data.Map.Map' with types as keys, where each value has the type of its key. In
51+addition to that, each value is wrapped in an interpretation @f@.
52+
53+Here is an example of using 'Prelude.Maybe' as an interpretation, with a
54+comparison to 'Data.Map.Map':
55+
56+@
57+ 'Data.Map.Map' 'Prelude.String' ('Prelude.Maybe' 'Prelude.String') 'TypeRepMap' 'Prelude.Maybe'
58+--------------------------- ---------------------
59+ \"Int\" -> Just \"5\" 'Prelude.Int' -> Just 5
60+ \"Bool\" -> Just \"True\" 'Prelude.Bool' -> Just 'Prelude.True'
61+ \"Char\" -> Nothing 'Prelude.Char' -> Nothing
62+@
63+
64+The runtime representation of 'TypeRepMap' is an array, not a tree. This makes
65+'lookup' significantly more efficient.
66+
67+-}
68−data TypeRepMap (f :: k -> Type) = TypeRepMap
68+data TypeRepMap (f :: k -> Type) =
69+ TypeRepMap
69− { fingerprintAs :: {-# UNPACK #-} !(PrimArray Word64)
70+ { fingerprintAs :: {-# UNPACK #-} !(PrimArray Word64) -- ^ first components of key fingerprints
70− , fingerprintBs :: {-# UNPACK #-} !(PrimArray Word64)
71+ , fingerprintBs :: {-# UNPACK #-} !(PrimArray Word64) -- ^ second components of key fingerprints
71− , anys :: {-# UNPACK #-} !(Array Any)
72+ , anys :: {-# UNPACK #-} !(Array Any) -- ^ values stored in the map
72 }
73 }
74+ -- ^ an unsafe constructor for 'TypeRepMap'
73
75
74-- | Shows only 'Fingerprint's.
76-- | Shows only 'Fingerprint's.
75instance Show (TypeRepMap f) where
77instance Show (TypeRepMap f) where
@@ -92,17 +94,38 @@ toFingerprints :: TypeRepMap f -> [Fingerprint]
92toFingerprints TypeRepMap{..} =
94toFingerprints TypeRepMap{..} =
93 zipWith Fingerprint (GHC.toList fingerprintAs) (GHC.toList fingerprintBs)
95 zipWith Fingerprint (GHC.toList fingerprintAs) (GHC.toList fingerprintBs)
94
96
95−-- | Empty structure.
97+{- |
98+
99+A 'TypeRepMap' with no values stored in it.
100+
101+prop> size empty == 0
102+prop> member @a empty == False
103+
104+-}
96empty :: TypeRepMap f
105empty :: TypeRepMap f
97empty = mempty
106empty = mempty
98{-# INLINE empty #-}
107{-# INLINE empty #-}
99
108
109+{- |
110+
100−-- | Construct a 'TypeRepMap' with a single element.
111+Construct a 'TypeRepMap' with a single element.
112+
113+prop> size (one x) == 1
114+prop> member @a (one (x :: f a)) == True
115+
116+-}
101one :: forall a f . Typeable a => f a -> TypeRepMap f
117one :: forall a f . Typeable a => f a -> TypeRepMap f
102one x = insert x empty
118one x = insert x empty
103{-# INLINE one #-}
119{-# INLINE one #-}
104
120
105−-- | Inserts the value with its type as a key.
121+{- |
122+
123+Insert a value into a 'TypeRepMap'.
124+
125+prop> size (insert v tm) >= size tm
126+prop> member @a (insert (x :: f a) tm) == True
127+
128+-}
106insert :: forall a f . Typeable a => f a -> TypeRepMap f -> TypeRepMap f
129insert :: forall a f . Typeable a => f a -> TypeRepMap f -> TypeRepMap f
107insert x = fromListPairs . addX . toPairList
130insert x = fromListPairs . addX . toPairList
108 where
131 where
@@ -113,41 +136,45 @@ insert x = fromListPairs . addX . toPairList
113 addX l = pairX : deleteByFst fpX l
136 addX l = pairX : deleteByFst fpX l
114{-# INLINE insert #-}
137{-# INLINE insert #-}
115
138
116−-- Helper type to workaround some issues with types
139+-- Extract the kind of a type. We use it to work around lack of syntax for
140+-- inferred type variables (which are not subject to type applications).
117type KindOf (a :: k) = k
141type KindOf (a :: k) = k
118
142
119−{- | Deletes value from list.
143+{- | Delete a value from a 'TypeRepMap'.
144+
145+prop> size (delete @a tm) <= size tm
146+prop> member @a (delete @a tm) == False
120
147
121−>>> let trMap = delete @Bool $ insert (Identity True) $ one (Identity 'a')
148+>>> tm = delete @Bool $ insert (Just True) $ one (Just 'a')
122−>>> size trMap
149+>>> size tm
1231
1501
124−>>> member @Bool trMap
151+>>> member @Bool tm
125False
152False
126−>>> member @Char trMap
153+>>> member @Char tm
127True
154True
128-}
155-}
129delete :: forall a (f :: KindOf a -> Type) . Typeable a => TypeRepMap f -> TypeRepMap f
156delete :: forall a (f :: KindOf a -> Type) . Typeable a => TypeRepMap f -> TypeRepMap f
130delete = fromListPairs . deleteByFst (typeFp @a) . toPairList
157delete = fromListPairs . deleteByFst (typeFp @a) . toPairList
131{-# INLINE delete #-}
158{-# INLINE delete #-}
132
159
133−{- | Map over elements.
160+{- | Map over the elements of a 'TypeRepMap'.
134
161
135−>>> let trMap = insert (Identity True) $ one (Identity 'a')
162+>>> tm = insert (Identity True) $ one (Identity 'a')
136−>>> lookup @Bool trMap
163+>>> lookup @Bool tm
137Just (Identity True)
164Just (Identity True)
138−>>> lookup @Char trMap
165+>>> lookup @Char tm
139Just (Identity 'a')
166Just (Identity 'a')
140−>>> let trMap2 = hoist ((:[]) . runIdentity) trMap
167+>>> tm2 = hoist ((:[]) . runIdentity) tm
141−>>> lookup @Bool trMap2
168+>>> lookup @Bool tm2
142Just [True]
169Just [True]
143−>>> lookup @Char trMap2
170+>>> lookup @Char tm2
144Just "a"
171Just "a"
145-}
172-}
146hoist :: (forall x. f x -> g x) -> TypeRepMap f -> TypeRepMap g
173hoist :: (forall x. f x -> g x) -> TypeRepMap f -> TypeRepMap g
147hoist f (TypeRepMap as bs ans) = TypeRepMap as bs $ mapArray' (toAny . f . fromAny) ans
174hoist f (TypeRepMap as bs ans) = TypeRepMap as bs $ mapArray' (toAny . f . fromAny) ans
148{-# INLINE hoist #-}
175{-# INLINE hoist #-}
149
176
150−-- | The union with a combining function.
177+-- | The union of two 'TypeRepMap's using a combining function.
151unionWith :: (forall x. f x -> f x -> f x) -> TypeRepMap f -> TypeRepMap f -> TypeRepMap f
178unionWith :: (forall x. f x -> f x -> f x) -> TypeRepMap f -> TypeRepMap f -> TypeRepMap f
152unionWith f m1 m2 = fromListPairs
179unionWith f m1 m2 = fromListPairs
153 $ Map.toList
180 $ Map.toList
@@ -159,13 +186,13 @@ unionWith f m1 m2 = fromListPairs
159 combine a b = toAny $ f (fromAny a) (fromAny b)
186 combine a b = toAny $ f (fromAny a) (fromAny b)
160{-# INLINE unionWith #-}
187{-# INLINE unionWith #-}
161
188
162−-- | The (left-biased) union of two maps. It prefers the first map when
189+-- | The (left-biased) union of two 'TypeRepMap's. It prefers the first map when
163-- duplicate keys are encountered, i.e. @'union' == 'unionWith' const@.
190-- duplicate keys are encountered, i.e. @'union' == 'unionWith' const@.
164union :: TypeRepMap f -> TypeRepMap f -> TypeRepMap f
191union :: TypeRepMap f -> TypeRepMap f -> TypeRepMap f
165union = unionWith const
192union = unionWith const
166{-# INLINE union #-}
193{-# INLINE union #-}
167
194
168−{- | Returns 'True' if there exist value of given type.
195+{- | Check if a value of the given type is present in a 'TypeRepMap'.
169
196
170>>> member @Char $ one (Identity 'a')
197>>> member @Char $ one (Identity 'a')
171True
198True
@@ -173,14 +200,14 @@ True
173False
200False
174-}
201-}
175member :: forall a (f :: KindOf a -> Type) . Typeable a => TypeRepMap f -> Bool
202member :: forall a (f :: KindOf a -> Type) . Typeable a => TypeRepMap f -> Bool
176−member trMap = case lookup @a trMap of
203+member tm = case lookup @a tm of
177 Nothing -> False
204 Nothing -> False
178 Just _ -> True
205 Just _ -> True
179{-# INLINE member #-}
206{-# INLINE member #-}
180
207
181−{- | Looks up the value at the type.
208+{- | Lookup a value of the given type in a 'TypeRepMap'.
182
209
183−>>> let x = lookup $ insert (Identity (11 :: Int)) empty
210+>>> x = lookup $ insert (Identity (11 :: Int)) empty
184>>> x :: Maybe (Identity Int)
211>>> x :: Maybe (Identity Int)
185Just (Identity 11)
212Just (Identity 11)
186>>> x :: Maybe (Identity ())
213>>> x :: Maybe (Identity ())
@@ -193,7 +220,7 @@ lookup tVect = fromAny . (anys tVect `indexArray`)
193 (fingerprintBs tVect)
220 (fingerprintBs tVect)
194{-# INLINE lookup #-}
221{-# INLINE lookup #-}
195
222
196−-- | Returns the size of the 'TypeRepMap'.
223+-- | Get the amount of elements in a 'TypeRepMap'.
197size :: TypeRepMap f -> Int
224size :: TypeRepMap f -> Int
198size = sizeofPrimArray . fingerprintAs
225size = sizeofPrimArray . fingerprintAs
199{-# INLINE size #-}
226{-# INLINE size #-}
@@ -236,7 +263,7 @@ typeFp = typeRepFingerprint $ typeRep $ Proxy @a
236{-# INLINE typeFp #-}
263{-# INLINE typeFp #-}
237
264
238toPairList :: TypeRepMap f -> [(Fingerprint, Any)]
265toPairList :: TypeRepMap f -> [(Fingerprint, Any)]
239−toPairList trMap = zip (toFingerprints trMap) (GHC.toList $ anys trMap)
266+toPairList tm = zip (toFingerprints tm) (GHC.toList $ anys tm)
240
267
241deleteByFst :: Eq a => a -> [(a, b)] -> [(a, b)]
268deleteByFst :: Eq a => a -> [(a, b)] -> [(a, b)]
242deleteByFst x = filter ((/= x) . fst)
269deleteByFst x = filter ((/= x) . fst)
test/Test/TypeRep/CacheMap.hs+2−2
@@ -5,8 +5,8 @@ import Prelude hiding (lookup)
5import Data.Functor.Identity (Identity (..))
5import Data.Functor.Identity (Identity (..))
6import Test.Tasty.Hspec (Spec, describe, it, shouldBe)
6import Test.Tasty.Hspec (Spec, describe, it, shouldBe)
7
7
8−import Data.TypeRep.Map (TF (..), fromList)
8+import Data.TypeRepMap.Internal (TF (..), fromList)
9−import Data.TypeRep.TMap (TMap, empty, insert, lookup, one, size, union)
9+import Data.TMap (TMap, empty, insert, lookup, one, size, union)
10
10
11-- Simple test for 'lookup', 'insert' and 'size' functions.
11-- Simple test for 'lookup', 'insert' and 'size' functions.
12spec_insertLookup :: Spec
12spec_insertLookup :: Spec
test/Test/TypeRep/MapProperty.hs+1−1
@@ -17,7 +17,7 @@ import Hedgehog (MonadGen, PropertyT, forAll, property, (===))
17import Test.Tasty (TestName, TestTree)
17import Test.Tasty (TestName, TestTree)
18import Test.Tasty.Hedgehog (testProperty)
18import Test.Tasty.Hedgehog (testProperty)
19
19
20−import Data.TypeRep.Map (TF (..), TypeRepMap (..), delete, fromList, insert, lookup, member)
20+import Data.TypeRepMap.Internal (TF (..), TypeRepMap (..), delete, fromList, insert, lookup, member)
21
21
22import qualified Hedgehog.Gen as Gen
22import qualified Hedgehog.Gen as Gen
23import qualified Hedgehog.Range as Range
23import qualified Hedgehog.Range as Range
typerep-map.cabal+19−4
@@ -1,7 +1,21 @@
1name: typerep-map
1name: typerep-map
2version: 0.1.0
2version: 0.1.0
3−synopsis: Efficient implementation of data type with types as keys
3+synopsis: Efficient implementation of a dependent map with types as keys
4−description: See README.md for more details.
4+description:
5+ A dependent map from type representations to values of these types.
6+ .
7+ Here is an illustration of such a map:
8+ .
9+ > TMap
10+ > ---------------
11+ > Int -> 5
12+ > Bool -> True
13+ > Char -> 'x'
14+ .
15+ In addition to @TMap@, we provide @TypeRepMap@ parametrized by a
16+ @vinyl@-style interpretation. This data structure is equivalent to @DMap
17+ TypeRep@, but with significantly more efficient lookups.
18+
5homepage: https://github.com/kowainik/typerep-map
19homepage: https://github.com/kowainik/typerep-map
6bug-reports: https://github.com/kowainik/typerep-map/issues
20bug-reports: https://github.com/kowainik/typerep-map/issues
7license: MIT
21license: MIT
@@ -23,8 +37,9 @@ source-repository head
23
37
24library
38library
25 hs-source-dirs: src
39 hs-source-dirs: src
26− exposed-modules: Data.TypeRep.Map
40+ exposed-modules: Data.TMap
27− Data.TypeRep.TMap
41+ Data.TypeRepMap
42+ Data.TypeRepMap.Internal
28 ghc-options: -Wall
43 ghc-options: -Wall
29 build-depends: base >= 4.9 && < 5
44 build-depends: base >= 4.9 && < 5
30 , containers
45 , containers