on 92b6021 help sign in
170 lines 4.0 kB history raw
1{-# LANGUAGE AllowAmbiguousTypes #-}
2{-# LANGUAGE Rank2Types #-}
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.
8Here is an example of a 'TMap' with a comparison to 'Data.Map.Map':
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\'
18The runtime representation of 'TMap' is an array, not a tree. This makes
19'lookup' significantly more efficient.
21-}
23module Data.TMap
24 ( -- * Map type
25 TMap
27 -- * Construction
28 , empty
29 , one
31 -- * Modification
32 , insert
33 , delete
34 , unionWith
35 , union
36 , map
37 , adjust
39 -- * Query
40 , lookup
41 , member
42 , size
43 , keys
44 ) where
46import Prelude hiding (lookup, map)
48import Data.Functor.Identity (Identity (..))
49import Data.Typeable (Typeable)
50import GHC.Exts (coerce)
51import Type.Reflection (SomeTypeRep)
53import qualified Data.TypeRepMap as F
55-- | 'TMap' is a special case of 'F.TypeRepMap' when the interpretation is
56-- 'Identity'.
57type TMap = F.TypeRepMap Identity
59{- |
61A 'TMap' with no values stored in it.
63prop> size empty == 0
64prop> member @a empty == False
66-}
67empty :: TMap
68empty = F.empty
69{-# INLINE empty #-}
71{- |
73Construct a 'TMap' with a single element.
75prop> size (one x) == 1
76prop> member @a (one (x :: a)) == True
78-}
79one :: forall a . Typeable a => a -> TMap
80one x = coerce (F.one @a @Identity $ coerce x)
81{-# INLINE one #-}
83{- |
85Insert a value into a 'TMap'.
87prop> size (insert v tm) >= size tm
88prop> member @a (insert (x :: a) tm) == True
90-}
91insert :: forall a . Typeable a => a -> TMap -> TMap
92insert x = coerce (F.insert @a @Identity $ coerce x)
93{-# INLINE insert #-}
95{- | Delete a value from a 'TMap'.
97prop> size (delete @a tm) <= size tm
98prop> member @a (delete @a tm) == False
100>>> tm = delete @Bool $ insert True $ one 'a'
101>>> size tm
103>>> member @Bool tm
104False
105>>> member @Char tm
106True
107-}
108delete :: forall a . Typeable a => TMap -> TMap
109delete = F.delete @a @Identity
110{-# INLINE delete #-}
112-- | The union of two 'TMap's using a combining function.
113unionWith :: (forall x. x -> x -> x) -> TMap -> TMap -> TMap
114unionWith f = F.unionWith fId
115 where
116 fId :: forall y . Identity y -> Identity y -> Identity y
117 fId y1 y2 = Identity $ f (coerce y1) (coerce y2)
118{-# INLINE unionWith #-}
120-- | The (left-biased) union of two 'TMap's. It prefers the first map when
121-- duplicate keys are encountered, i.e. @'union' == 'unionWith' const@.
122union :: TMap -> TMap -> TMap
123union = F.union
124{-# INLINE union #-}
126{- | Lookup a value of the given type in a 'TMap'.
128>>> x = lookup $ insert (11 :: Int) empty
129>>> x :: Maybe Int
130Just 11
131>>> x :: Maybe ()
132Nothing
133-}
134lookup :: forall a. Typeable a => TMap -> Maybe a
135lookup = coerce (F.lookup @a @Identity)
136{-# INLINE lookup #-}
138{- | Check if a value of the given type is present in a 'TMap'.
140>>> member @Char $ one 'a'
141True
142>>> member @Bool $ one 'a'
143False
144-}
145member :: forall a . Typeable a => TMap -> Bool
146member = F.member @a @Identity
147{-# INLINE member #-}
149-- | Get the amount of elements in a 'TMap'.
150size :: TMap -> Int
151size = F.size
152{-# INLINE size #-}
154-- | Returns the list of 'SomeTypeRep's from keys.
155keys :: TMap -> [SomeTypeRep]
156keys = F.keys
157{-# INLINE keys #-}
159-- | Map a function over the values.
160map :: (forall a. Typeable a => a -> a) -> TMap -> TMap
161map f = F.hoistWithKey (liftToIdentity f)
162{-# INLINE map #-}
164-- | Update a value with the result of the provided function.
165adjust :: Typeable a => (a -> a) -> TMap -> TMap
166adjust f = F.adjust (liftToIdentity f)
167{-# INLINE adjust #-}
169liftToIdentity :: forall a. Typeable a => (a -> a) -> Identity a -> Identity a
170liftToIdentity = coerce