@@ -1,10 +1,11 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
1−{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE GADTs #-}
4+{-# LANGUAGE GADTs #-}
4−{-# LANGUAGE KindSignatures #-}
5+{-# LANGUAGE KindSignatures #-}
5−{-# LANGUAGE MagicHash #-}
6+{-# LANGUAGE MagicHash #-}
6−{-# LANGUAGE PolyKinds #-}
7+{-# LANGUAGE TypeInType #-}
7−{-# LANGUAGE TypeFamilies #-}
8+{-# LANGUAGE TypeFamilies #-}
9-- {-# OPTIONS_GHC -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes #-}
10-- {-# OPTIONS_GHC -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes #-}
@@ -14,8 +15,11 @@ module Data.TypeRep.CacheMap
15 -- 'TypeRepMap' interface
16 -- 'TypeRepMap' interface
21 -- * Helpful testing functions
25 -- * Helpful testing functions
@@ -34,7 +38,6 @@ import Data.List (nubBy)
34import Data.Maybe (fromJust)
38import Data.Maybe (fromJust)
35import Data.Proxy (Proxy (..))
39import Data.Proxy (Proxy (..))
36import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
40import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
37−import Data.Word (Word64)
38import GHC.Base (Any, Int (..), Int#, (*#), (+#), (<#))
41import GHC.Base (Any, Int (..), Int#, (*#), (+#), (<#))
39import GHC.Exts (inline, sortWith)
42import GHC.Exts (inline, sortWith)
40import GHC.Fingerprint (Fingerprint (..))
43import GHC.Fingerprint (Fingerprint (..))
@@ -57,7 +60,7 @@ data TypeRepMap (f :: k -> Type) = TypeRepMap
57instance Show (TypeRepMap f) where
60instance Show (TypeRepMap f) where
58 show = show . toFps
61 show = show . toFps
60−-- | Returnes the list of 'Fingerprint's from 'TypeRepMap'.
63+-- | Returns the list of 'Fingerprint's from 'TypeRepMap'.
61toFps :: TypeRepMap f -> [Fingerprint]
64toFps :: TypeRepMap f -> [Fingerprint]
62toFps TypeRepMap{..} = zipWith Fingerprint
65toFps TypeRepMap{..} = zipWith Fingerprint
63 (Unboxed.toList fingerprintAs)
66 (Unboxed.toList fingerprintAs)
@@ -70,20 +73,52 @@ fromAny = unsafeCoerce
70empty :: TypeRepMap f
73empty :: TypeRepMap f
71empty = TypeRepMap mempty mempty mempty
74empty = TypeRepMap mempty mempty mempty
76+-- | Construct a 'TypeRepMap' with a single element.
77+one :: forall a f . Typeable a => f a -> TypeRepMap f
78+one x = insert x empty
73-- | Inserts the value with its type as a key.
81-- | Inserts the value with its type as a key.
74insert :: forall a f . Typeable a => f a -> TypeRepMap f -> TypeRepMap f
82insert :: forall a f . Typeable a => f a -> TypeRepMap f -> TypeRepMap f
75insert x = fromListPairs . addX . toPairList
83insert x = fromListPairs . addX . toPairList
77− toPairList :: TypeRepMap f -> [(Fingerprint, Any)]
78− toPairList trMap = zip (toFps trMap) (V.toList $ anys trMap)
80 pairX :: (Fingerprint, Any)
85 pairX :: (Fingerprint, Any)
81 pairX@(fpX, _) = (calcFp x, unsafeCoerce x)
86 pairX@(fpX, _) = (calcFp x, unsafeCoerce x)
83 addX :: [(Fingerprint, Any)] -> [(Fingerprint, Any)]
88 addX :: [(Fingerprint, Any)] -> [(Fingerprint, Any)]
84− addX l = pairX : filter ((/= fpX) . fst) l
89+ addX l = pairX : deleteByFst fpX l
85{-# INLINE insert #-}
90{-# INLINE insert #-}
92+-- Helper type to workaround some issues with types
93+type KindOf (a :: k) = k
95+{- | Deletes value from list.
97+>>> let trMap = delete @Bool $ insert (Identity True) $ one (Identity 'a')
100+>>> member @Bool trMap
102+>>> member @Char trMap
105+delete :: forall a (f :: KindOf a -> Type) . Typeable a => TypeRepMap f -> TypeRepMap f
106+delete = fromListPairs . deleteByFst (typeFp @a) . toPairList
107+{-# INLINE delete #-}
109+{- | Returns 'True' if there exist value of given type.
111+>>> member @Char $ one (Identity 'a')
113+>>> member @Bool $ one (Identity 'a')
116+member :: forall a (f :: KindOf a -> Type) . Typeable a => TypeRepMap f -> Bool
117+member trMap = case lookup @a trMap of
120+{-# INLINE member #-}
87{- | Looks up the value at the type.
122{- | Looks up the value at the type.
89>>> let x = lookup $ insert (Identity (11 :: Int)) empty
124>>> let x = lookup $ insert (Identity (11 :: Int)) empty
@@ -91,11 +126,10 @@ insert x = fromListPairs . addX . toPairList
91Just (Identity 11)
126Just (Identity 11)
92>>> x :: Maybe (Identity ())
127>>> x :: Maybe (Identity ())
96lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
130lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
97lookup tVect = fromAny . (anys tVect V.!)
131lookup tVect = fromAny . (anys tVect V.!)
98− <$> cachedBinarySearch (typeRepFingerprint $ typeRep $ Proxy @a)
132+ <$> cachedBinarySearch (typeFp @a)
99 (fingerprintAs tVect)
133 (fingerprintAs tVect)
100 (fingerprintBs tVect)
134 (fingerprintBs tVect)
101{-# INLINE lookup #-}
135{-# INLINE lookup #-}
@@ -128,6 +162,23 @@ cachedBinarySearch (Fingerprint (W64# a) (W64# b)) fpAs fpBs = inline (go 0#)
128 len = let !(I# l) = Unboxed.length fpAs in l
162 len = let !(I# l) = Unboxed.length fpAs in l
129{-# INLINE cachedBinarySearch #-}
163{-# INLINE cachedBinarySearch #-}
165+----------------------------------------------------------------------------
166+-- Internal functions
167+----------------------------------------------------------------------------
169+typeFp :: forall a . Typeable a => Fingerprint
170+typeFp = typeRepFingerprint $ typeRep $ Proxy @a
171+{-# INLINE typeFp #-}
173+toPairList :: TypeRepMap f -> [(Fingerprint, Any)]
174+toPairList trMap = zip (toFps trMap) (V.toList $ anys trMap)
176+deleteByFst :: Eq a => a -> [(a, b)] -> [(a, b)]
177+deleteByFst x = filter ((/= x) . fst)
179+nubByFst :: (Eq a) => [(a, b)] -> [(a, b)]
180+nubByFst = nubBy ((==) `on` fst)
131----------------------------------------------------------------------------
182----------------------------------------------------------------------------
132-- Functions for testing and benchmarking
183-- Functions for testing and benchmarking
133----------------------------------------------------------------------------
184----------------------------------------------------------------------------
@@ -165,10 +216,7 @@ fromListPairs :: [(Fingerprint, Any)] -> TypeRepMap f
165fromListPairs kvs = TypeRepMap (Unboxed.fromList fpAs) (Unboxed.fromList fpBs) (V.fromList ans)
216fromListPairs kvs = TypeRepMap (Unboxed.fromList fpAs) (Unboxed.fromList fpBs) (V.fromList ans)
167 (fpAs, fpBs) = unzip $ map (\(Fingerprint a b) -> (a, b)) fps
218 (fpAs, fpBs) = unzip $ map (\(Fingerprint a b) -> (a, b)) fps
168− (fps, ans) = unzip $ fromSortedList $ sortWith fst $ nubPairs kvs
219+ (fps, ans) = unzip $ fromSortedList $ sortWith fst $ nubByFst kvs
170−nubPairs :: (Eq a) => [(a, b)] -> [(a, b)]
171−nubPairs = nubBy ((==) `on` fst)
173----------------------------------------------------------------------------
221----------------------------------------------------------------------------
174-- Tree-like conversion
222-- Tree-like conversion