@@ -46,15 +46,18 @@ import qualified Data.IntMap.Strict as IM
46import qualified Data.Vector as V
46import qualified Data.Vector as V
47import qualified Data.Vector.Unboxed as Unboxed
47import qualified Data.Vector.Unboxed as Unboxed
49+-- | Map-like data structure that keeps types as keys.
49data TypeRepMap (f :: k -> Type) = TypeRepMap
50data TypeRepMap (f :: k -> Type) = TypeRepMap
50 { fingerprintAs :: Unboxed.Vector Word64
51 { fingerprintAs :: Unboxed.Vector Word64
51 , fingerprintBs :: Unboxed.Vector Word64
52 , fingerprintBs :: Unboxed.Vector Word64
52 , anys :: V.Vector Any
53 , anys :: V.Vector Any
56+-- | Shows only 'Fingerprint's.
55instance Show (TypeRepMap f) where
57instance Show (TypeRepMap f) where
56 show = show . toFps
58 show = show . toFps
60+-- | Returnes the list of 'Fingerprint's from 'TypeRepMap'.
58toFps :: TypeRepMap f -> [Fingerprint]
61toFps :: TypeRepMap f -> [Fingerprint]
59toFps TypeRepMap{..} = zipWith Fingerprint
62toFps TypeRepMap{..} = zipWith Fingerprint
60 (Unboxed.toList fingerprintAs)
63 (Unboxed.toList fingerprintAs)
@@ -81,12 +84,15 @@ insert x = fromListPairs . addX . toPairList
81 addX l = pairX : filter ((/= fpX) . fst) l
84 addX l = pairX : filter ((/= fpX) . fst) l
82{-# INLINE insert #-}
85{-# INLINE insert #-}
84−-- | Looks up the value at the type.
87+{- | Looks up the value at the type.
85−-- >>> let x = lookup $ insert (11 :: Int) empty
89+>>> let x = lookup $ insert (Identity (11 :: Int)) empty
86−-- >>> x :: Maybe Int
90+>>> x :: Maybe (Identity Int)
87−-- Just 11
91+Just (Identity 11)
88−-- >>> x :: Maybe ()
92+>>> x :: Maybe (Identity ())
90lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
96lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
91lookup tVect = fromAny . (anys tVect V.!)
97lookup tVect = fromAny . (anys tVect V.!)
92 <$> cachedBinarySearch (typeRepFingerprint $ typeRep $ Proxy @a)
98 <$> cachedBinarySearch (typeRepFingerprint $ typeRep $ Proxy @a)
@@ -97,6 +103,7 @@ lookup tVect = fromAny . (anys tVect V.!)
97-- | Returns the size of the 'TypeRepMap'.
103-- | Returns the size of the 'TypeRepMap'.
98size :: TypeRepMap f -> Int
104size :: TypeRepMap f -> Int
99size = Unboxed.length . fingerprintAs
105size = Unboxed.length . fingerprintAs
101-- | Binary searched based on this article
108-- | Binary searched based on this article
102-- http://bannalia.blogspot.com/2015/06/cache-friendly-binary-search.html
109-- http://bannalia.blogspot.com/2015/06/cache-friendly-binary-search.html
@@ -125,12 +132,29 @@ cachedBinarySearch (Fingerprint (W64# a) (W64# b)) fpAs fpBs = inline (go 0#)
125-- Functions for testing and benchmarking
132-- Functions for testing and benchmarking
126----------------------------------------------------------------------------
133----------------------------------------------------------------------------
135+-- | Existential wrapper around 'Typeable' indexed by @f@ type parameter.
136+-- Useful for 'TypeRepMap' structure creation form list of 'TF's.
128data TF f where
137data TF f where
129 TF :: Typeable a => f a -> TF f
138 TF :: Typeable a => f a -> TF f
131instance Show (TF f) where
140instance Show (TF f) where
132 show (TF tf) = show $ calcFp tf
141 show (TF tf) = show $ calcFp tf
143+{- | Creates 'TypeRepMap' from a list of 'TF's.
145+>>> size $ fromList [TF $ Identity True, TF $ Identity 'a']
149+fromList :: forall f . [TF f] -> TypeRepMap f
150+fromList = fromListPairs . map (fp &&& an)
152+ fp :: TF f -> Fingerprint
153+ fp (TF x) = calcFp x
156+ an (TF x) = unsafeCoerce x
134fromF :: Typeable a => f a -> Proxy a
158fromF :: Typeable a => f a -> Proxy a
135fromF _ = Proxy
159fromF _ = Proxy
@@ -143,15 +167,6 @@ fromListPairs kvs = TypeRepMap (Unboxed.fromList fpAs) (Unboxed.fromList fpBs) (
143 (fpAs, fpBs) = unzip $ map (\(Fingerprint a b) -> (a, b)) fps
167 (fpAs, fpBs) = unzip $ map (\(Fingerprint a b) -> (a, b)) fps
144 (fps, ans) = unzip $ fromSortedList $ sortWith fst $ nubPairs kvs
168 (fps, ans) = unzip $ fromSortedList $ sortWith fst $ nubPairs kvs
146−fromList :: forall f . [TF f] -> TypeRepMap f
147−fromList = fromListPairs . map (fp &&& an)
149− fp :: TF f -> Fingerprint
150− fp (TF x) = calcFp x
153− an (TF x) = unsafeCoerce x
155nubPairs :: (Eq a) => [(a, b)] -> [(a, b)]
170nubPairs :: (Eq a) => [(a, b)] -> [(a, b)]
156nubPairs = nubBy ((==) `on` fst)
171nubPairs = nubBy ((==) `on` fst)