on main help sign in
Update documentation and module structure (#38)
commit2df2fcd0ea073f364ad6fcdfc20b6a0037e01e3d authorVladislav Zavialov <vlad.z.4096@gmail.com> dateTue 10 Jul 2018, 17:04 (8 years ago) parent77c267f
9 files changed+335−167
README.md+16−14 benchmark/CacheMap.hs+1−1 src/Data/TMap.hs+148 src/Data/TypeRep/TMap.hs−89 src/Data/TypeRepMap.hs+65 src/Data/TypeRep/Map.hs → src/Data/TypeRepMap/Internal.hs+83−56 test/Test/TypeRep/CacheMap.hs+2−2 test/Test/TypeRep/MapProperty.hs+1−1 typerep-map.cabal+19−4
README.md+16−14
@@ -4,36 +4,38 @@
44[![Build status](https://secure.travis-ci.org/kowainik/typerep-map.svg)](https://travis-ci.org/kowainik/typerep-map)
55[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/vrom911/typerep-map/blob/master/LICENSE)
66
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.
88
99## Usage example
1010
1111```haskell
12−ghci> let typeRepMap = insert (Identity True) $ one (Identity (42 :: Int))
12+ghci> import Data.TMap
1313
14−ghci> size typeRepMap
14+ghci> tm = insert True $ one (42 :: Int)
15+
16+ghci> size tm
15172
1618
17−ghci> let res = lookup typeRepMap
19+ghci> res = lookup tm
1820
19−ghci> res :: Maybe (Identity Int)
20−Just (Identity 42)
21+ghci> res :: Maybe Int
22+Just 42
2123
22−ghci> res :: Maybe (Identity Bool)
23−Just (Identity True)
24+ghci> res :: Maybe Bool
25+Just True
2426
25−ghci> res :: Maybe (Identity String)
27+ghci> res :: Maybe String
2628Nothing
2729
28−ghci> lookup (insert (Identity "hello") typeRepMap) :: Maybe (Identity String)
29−Just (Identity "hello")
30+ghci> lookup (insert "hello" tm) :: Maybe String
31+Just "hello"
3032
31−ghci> member @Int typeRepMap
33+ghci> member @Int tm
3234True
3335
34−ghci> let trMap = delete @Int typeRepMap
36+ghci> tm' = delete @Int tm
3537
36−ghci> member @Int trMap
38+ghci> member @Int tm'
3739False
3840```
3941
benchmark/CacheMap.hs+1−1
@@ -21,7 +21,7 @@ import Data.Proxy (Proxy (..))
2121import Data.Typeable (Typeable)
2222import GHC.TypeLits
2323
24−import Data.TypeRep.Map (TF (..), TypeRepMap (..), fromList, lookup)
24+import Data.TypeRepMap.Internal (TF (..), TypeRepMap (..), fromList, lookup)
2525
2626benchCacheMap :: Benchmark
2727benchCacheMap = 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 @@
1212
1313-- {-# OPTIONS_GHC -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes #-}
1414
15−-- | This module introduces the 'TypeRepMap' data structure and functions to work with it.
16−
17−module Data.TypeRep.Map
18− ( -- * Map type
19− TypeRepMap (..)
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
15+-- | Internal API for 'TypeRepMap' and operations on it. The functions here do
16+-- not have any stability guarantees and can change between minor versions.
17+--
18+-- If you need to use this module for purposes other than tests,
19+-- create an issue.
20+--
21+module Data.TypeRepMap.Internal where
4222
4323import Prelude hiding (lookup)
4424
@@ -64,12 +44,34 @@ import qualified Data.IntMap.Strict as IM
6444import qualified Data.Map.Strict as Map
6545import qualified GHC.Exts as GHC (fromList, toList)
6646
67−-- | Map-like data structure that keeps types as keys.
68−data TypeRepMap (f :: k -> Type) = TypeRepMap
69− { fingerprintAs :: {-# UNPACK #-} !(PrimArray Word64)
70− , fingerprintBs :: {-# UNPACK #-} !(PrimArray Word64)
71− , anys :: {-# UNPACK #-} !(Array Any)
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) =
69+ TypeRepMap
70+ { fingerprintAs :: {-# UNPACK #-} !(PrimArray Word64) -- ^ first components of key fingerprints
71+ , fingerprintBs :: {-# UNPACK #-} !(PrimArray Word64) -- ^ second components of key fingerprints
72+ , anys :: {-# UNPACK #-} !(Array Any) -- ^ values stored in the map
7273 }
74+ -- ^ an unsafe constructor for 'TypeRepMap'
7375
7476-- | Shows only 'Fingerprint's.
7577instance Show (TypeRepMap f) where
@@ -92,17 +94,38 @@ toFingerprints :: TypeRepMap f -> [Fingerprint]
9294toFingerprints TypeRepMap{..} =
9395 zipWith Fingerprint (GHC.toList fingerprintAs) (GHC.toList fingerprintBs)
9496
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+-}
96105empty :: TypeRepMap f
97106empty = mempty
98107{-# INLINE empty #-}
99108
100−-- | Construct a 'TypeRepMap' with a single element.
109+{- |
110+
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+-}
101117one :: forall a f . Typeable a => f a -> TypeRepMap f
102118one x = insert x empty
103119{-# INLINE one #-}
104120
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+-}
106129insert :: forall a f . Typeable a => f a -> TypeRepMap f -> TypeRepMap f
107130insert x = fromListPairs . addX . toPairList
108131 where
@@ -113,41 +136,45 @@ insert x = fromListPairs . addX . toPairList
113136 addX l = pairX : deleteByFst fpX l
114137{-# INLINE insert #-}
115138
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).
117141type KindOf (a :: k) = k
118142
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
120147
121−>>> let trMap = delete @Bool $ insert (Identity True) $ one (Identity 'a')
122−>>> size trMap
148+>>> tm = delete @Bool $ insert (Just True) $ one (Just 'a')
149+>>> size tm
1231501
124−>>> member @Bool trMap
151+>>> member @Bool tm
125152False
126−>>> member @Char trMap
153+>>> member @Char tm
127154True
128155-}
129156delete :: forall a (f :: KindOf a -> Type) . Typeable a => TypeRepMap f -> TypeRepMap f
130157delete = fromListPairs . deleteByFst (typeFp @a) . toPairList
131158{-# INLINE delete #-}
132159
133−{- | Map over elements.
160+{- | Map over the elements of a 'TypeRepMap'.
134161
135−>>> let trMap = insert (Identity True) $ one (Identity 'a')
136−>>> lookup @Bool trMap
162+>>> tm = insert (Identity True) $ one (Identity 'a')
163+>>> lookup @Bool tm
137164Just (Identity True)
138−>>> lookup @Char trMap
165+>>> lookup @Char tm
139166Just (Identity 'a')
140−>>> let trMap2 = hoist ((:[]) . runIdentity) trMap
141−>>> lookup @Bool trMap2
167+>>> tm2 = hoist ((:[]) . runIdentity) tm
168+>>> lookup @Bool tm2
142169Just [True]
143−>>> lookup @Char trMap2
170+>>> lookup @Char tm2
144171Just "a"
145172-}
146173hoist :: (forall x. f x -> g x) -> TypeRepMap f -> TypeRepMap g
147174hoist f (TypeRepMap as bs ans) = TypeRepMap as bs $ mapArray' (toAny . f . fromAny) ans
148175{-# INLINE hoist #-}
149176
150−-- | The union with a combining function.
177+-- | The union of two 'TypeRepMap's using a combining function.
151178unionWith :: (forall x. f x -> f x -> f x) -> TypeRepMap f -> TypeRepMap f -> TypeRepMap f
152179unionWith f m1 m2 = fromListPairs
153180 $ Map.toList
@@ -159,13 +186,13 @@ unionWith f m1 m2 = fromListPairs
159186 combine a b = toAny $ f (fromAny a) (fromAny b)
160187{-# INLINE unionWith #-}
161188
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
163190-- duplicate keys are encountered, i.e. @'union' == 'unionWith' const@.
164191union :: TypeRepMap f -> TypeRepMap f -> TypeRepMap f
165192union = unionWith const
166193{-# INLINE union #-}
167194
168−{- | Returns 'True' if there exist value of given type.
195+{- | Check if a value of the given type is present in a 'TypeRepMap'.
169196
170197>>> member @Char $ one (Identity 'a')
171198True
@@ -173,14 +200,14 @@ True
173200False
174201-}
175202member :: 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
177204 Nothing -> False
178205 Just _ -> True
179206{-# INLINE member #-}
180207
181−{- | Looks up the value at the type.
208+{- | Lookup a value of the given type in a 'TypeRepMap'.
182209
183−>>> let x = lookup $ insert (Identity (11 :: Int)) empty
210+>>> x = lookup $ insert (Identity (11 :: Int)) empty
184211>>> x :: Maybe (Identity Int)
185212Just (Identity 11)
186213>>> x :: Maybe (Identity ())
@@ -193,7 +220,7 @@ lookup tVect = fromAny . (anys tVect `indexArray`)
193220 (fingerprintBs tVect)
194221{-# INLINE lookup #-}
195222
196−-- | Returns the size of the 'TypeRepMap'.
223+-- | Get the amount of elements in a 'TypeRepMap'.
197224size :: TypeRepMap f -> Int
198225size = sizeofPrimArray . fingerprintAs
199226{-# INLINE size #-}
@@ -236,7 +263,7 @@ typeFp = typeRepFingerprint $ typeRep $ Proxy @a
236263{-# INLINE typeFp #-}
237264
238265toPairList :: TypeRepMap f -> [(Fingerprint, Any)]
239−toPairList trMap = zip (toFingerprints trMap) (GHC.toList $ anys trMap)
266+toPairList tm = zip (toFingerprints tm) (GHC.toList $ anys tm)
240267
241268deleteByFst :: Eq a => a -> [(a, b)] -> [(a, b)]
242269deleteByFst x = filter ((/= x) . fst)
test/Test/TypeRep/CacheMap.hs+2−2
@@ -5,8 +5,8 @@ import Prelude hiding (lookup)
55import Data.Functor.Identity (Identity (..))
66import Test.Tasty.Hspec (Spec, describe, it, shouldBe)
77
8−import Data.TypeRep.Map (TF (..), fromList)
9−import Data.TypeRep.TMap (TMap, empty, insert, lookup, one, size, union)
8+import Data.TypeRepMap.Internal (TF (..), fromList)
9+import Data.TMap (TMap, empty, insert, lookup, one, size, union)
1010
1111-- Simple test for 'lookup', 'insert' and 'size' functions.
1212spec_insertLookup :: Spec
test/Test/TypeRep/MapProperty.hs+1−1
@@ -17,7 +17,7 @@ import Hedgehog (MonadGen, PropertyT, forAll, property, (===))
1717import Test.Tasty (TestName, TestTree)
1818import Test.Tasty.Hedgehog (testProperty)
1919
20−import Data.TypeRep.Map (TF (..), TypeRepMap (..), delete, fromList, insert, lookup, member)
20+import Data.TypeRepMap.Internal (TF (..), TypeRepMap (..), delete, fromList, insert, lookup, member)
2121
2222import qualified Hedgehog.Gen as Gen
2323import qualified Hedgehog.Range as Range
typerep-map.cabal+19−4
@@ -1,7 +1,21 @@
11name: typerep-map
22version: 0.1.0
3−synopsis: Efficient implementation of data type with types as keys
4−description: See README.md for more details.
3+synopsis: Efficient implementation of a dependent map with types as keys
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+
519homepage: https://github.com/kowainik/typerep-map
620bug-reports: https://github.com/kowainik/typerep-map/issues
721license: MIT
@@ -23,8 +37,9 @@ source-repository head
2337
2438library
2539 hs-source-dirs: src
26− exposed-modules: Data.TypeRep.Map
27− Data.TypeRep.TMap
40+ exposed-modules: Data.TMap
41+ Data.TypeRepMap
42+ Data.TypeRepMap.Internal
2843 ghc-options: -Wall
2944 build-depends: base >= 4.9 && < 5
3045 , containers