on 39b92b4 help sign in
9 files changed+644−57
since splitsnapshots
unifiedsplit
benchmark/Main.hs+10−57 benchmark/Map.hs+61 benchmark/OptimalVector.hs+59 benchmark/Vector.hs+59 src/Data/TypeRep/OptimalVector.hs+177 src/Data/TypeRep/Vector.hs+188 test/Test/TypeRep/Vector.hs+41 test/Test/TypeRep/VectorOpt.hs+41 typerep-map.cabal+8
benchmark/Main.hs+10−57
@@ -1,61 +1,14 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE PolyKinds #-}
3−{-# LANGUAGE ExplicitForAll #-}
4−{-# LANGUAGE ExplicitNamespaces #-}
5−{-# LANGUAGE KindSignatures #-}
6−{-# LANGUAGE ScopedTypeVariables #-}
7−{-# LANGUAGE TypeFamilies #-}
8−{-# LANGUAGE TypeOperators #-}
9−{-# LANGUAGE UndecidableInstances #-}
1+module Main where
102
11−{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
3+import Criterion.Main (defaultMain)
124
13−import Criterion.Main (bench, defaultMain, nf, whnf)
14−
15−import Prelude hiding (lookup)
16−
17−import Control.DeepSeq (rnf)
18−import Control.Exception.Base (evaluate)
19−import Data.Maybe (fromJust)
20−import Data.Proxy (Proxy (..))
21−import Data.Typeable (Typeable)
22−import GHC.TypeLits
23−
24−import Data.TypeRep.Map (TypeRepMap (..), empty, insert, keys, lookup, size)
5+import Map (benchMap)
6+import OptimalVector (benchVectorOpt)
7+--import Vector (benchVector)
258
269main :: IO ()
27−main = do
28− putStrLn $ "size: " ++ (show $ size bigMap)
29− evaluate $ rknf bigMap
30− defaultMain
31− [ bench "lookup" $ nf tenLookups bigMap
32− , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)
33− , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)
34− ]
35−
36−tenLookups :: TypeRepMap (Proxy :: Nat -> *)
37− -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
38− , Proxy 50, Proxy 60, Proxy 70, Proxy 80
39− )
40−tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
41− where
42− lp :: forall (a::Nat). Typeable a => Proxy a
43− lp = fromJust $ lookup tmap
44−
45−-- TypeRepMap of 10000 elements
46−bigMap :: TypeRepMap (Proxy :: Nat -> *)
47−bigMap = buildBigMap 10000 (Proxy :: Proxy 0) empty
48−
49−data Z
50−data S a
51−
52−buildBigMap :: forall a . (Typeable a, KnownNat a) => Int -> Proxy (a :: Nat) -> TypeRepMap (Proxy :: Nat -> *) -> TypeRepMap (Proxy :: Nat -> *)
53−buildBigMap 1 x = insert x
54−buildBigMap n x = insert x . buildBigMap (n - 1) (Proxy :: Proxy (a + 1))
55−
56−rknf :: TypeRepMap f -> ()
57−rknf = rnf . keys
58−
59−type family BigProxy (n :: Nat) :: * where
60− BigProxy 0 = Z
61− BigProxy n = S (BigProxy (n - 1))
10+main = defaultMain
11+ [ benchMap
12+ --, benchVector
13+ , benchVectorOpt
14+ ]
benchmark/Map.hsnew file+61
@@ -0,0 +1,61 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExplicitForAll #-}
3+{-# LANGUAGE ExplicitNamespaces #-}
4+{-# LANGUAGE KindSignatures #-}
5+{-# LANGUAGE PolyKinds #-}
6+{-# LANGUAGE ScopedTypeVariables #-}
7+{-# LANGUAGE TypeFamilies #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE UndecidableInstances #-}
10+
11+{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
12+
13+module Map
14+ ( benchMap
15+ ) where
16+
17+import Criterion.Main (Benchmark, bench, bgroup, nf)
18+
19+import Prelude hiding (lookup)
20+
21+--import Control.DeepSeq (rnf)
22+import Data.Maybe (fromJust)
23+import Data.Proxy (Proxy (..))
24+import Data.Typeable (Typeable)
25+import GHC.TypeLits
26+
27+import Data.TypeRep.Map (TypeRepMap (..), empty, insert, lookup)
28+
29+benchMap :: Benchmark
30+benchMap = bgroup "map"
31+ [ bench "lookup" $ nf tenLookups bigMap
32+ --, bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)
33+ --, bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)
34+ ]
35+
36+tenLookups :: TypeRepMap (Proxy :: Nat -> *)
37+ -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
38+ , Proxy 50, Proxy 60, Proxy 70, Proxy 80
39+ )
40+tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
41+ where
42+ lp :: forall (a::Nat). Typeable a => Proxy a
43+ lp = fromJust $ lookup tmap
44+
45+-- TypeRepMap of 10000 elements
46+bigMap :: TypeRepMap (Proxy :: Nat -> *)
47+bigMap = buildBigMap 10000 (Proxy :: Proxy 0) empty
48+
49+data Z
50+data S a
51+
52+buildBigMap :: forall a . (Typeable a, KnownNat a) => Int -> Proxy (a :: Nat) -> TypeRepMap (Proxy :: Nat -> *) -> TypeRepMap (Proxy :: Nat -> *)
53+buildBigMap 1 x = insert x
54+buildBigMap n x = insert x . buildBigMap (n - 1) (Proxy :: Proxy (a + 1))
55+
56+--rknf :: TypeRepMap f -> ()
57+--rknf = rnf . keys
58+
59+type family BigProxy (n :: Nat) :: * where
60+ BigProxy 0 = Z
61+ BigProxy n = S (BigProxy (n - 1))
benchmark/OptimalVector.hsnew file+59
@@ -0,0 +1,59 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExplicitNamespaces #-}
3+{-# LANGUAGE KindSignatures #-}
4+{-# LANGUAGE PolyKinds #-}
5+{-# LANGUAGE ScopedTypeVariables #-}
6+{-# LANGUAGE TypeFamilies #-}
7+{-# LANGUAGE TypeOperators #-}
8+{-# LANGUAGE UndecidableInstances #-}
9+
10+{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
11+
12+module OptimalVector
13+ ( benchVectorOpt
14+ ) where
15+
16+import Criterion.Main (Benchmark, bench, bgroup, nf)
17+
18+import Prelude hiding (lookup)
19+
20+import Data.Maybe (fromJust)
21+import Data.Proxy (Proxy (..))
22+import Data.Typeable (Typeable)
23+import GHC.TypeLits
24+
25+import Data.TypeRep.OptimalVector
26+
27+benchVectorOpt :: Benchmark
28+benchVectorOpt = bgroup "vector optimal"
29+ [ bench "lookup" $ nf tenLookups bigMap
30+ -- , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)
31+ -- , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)
32+ ]
33+
34+tenLookups :: TypeRepVector (Proxy :: Nat -> *)
35+ -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
36+ , Proxy 50, Proxy 60, Proxy 70, Proxy 80
37+ )
38+tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
39+ where
40+ lp :: forall (a::Nat). Typeable a => Proxy a
41+ lp = fromJust $ lookup tmap
42+
43+-- TypeRepMap of 10000 elements
44+bigMap :: TypeRepVector (Proxy :: Nat -> *)
45+bigMap = fromList $ buildBigMap 10000 (Proxy :: Proxy 0) []
46+
47+data Z
48+data S a
49+
50+buildBigMap :: forall a . (Typeable a, KnownNat a) => Int -> Proxy (a :: Nat) -> [TF (Proxy :: Nat -> *)] -> [TF (Proxy :: Nat -> *)]
51+buildBigMap 1 x = (TF x :)
52+buildBigMap n x = (TF x :) . buildBigMap (n - 1) (Proxy :: Proxy (a + 1))
53+
54+-- rknf :: TypeRepMap f -> ()
55+-- rknf = rnf . keys
56+
57+type family BigProxy (n :: Nat) :: * where
58+ BigProxy 0 = Z
59+ BigProxy n = S (BigProxy (n - 1))
benchmark/Vector.hsnew file+59
@@ -0,0 +1,59 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExplicitNamespaces #-}
3+{-# LANGUAGE KindSignatures #-}
4+{-# LANGUAGE PolyKinds #-}
5+{-# LANGUAGE ScopedTypeVariables #-}
6+{-# LANGUAGE TypeFamilies #-}
7+{-# LANGUAGE TypeOperators #-}
8+{-# LANGUAGE UndecidableInstances #-}
9+
10+{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
11+
12+module Vector
13+ ( benchVector
14+ ) where
15+
16+import Criterion.Main (Benchmark, bench, bgroup, nf)
17+
18+import Prelude hiding (lookup)
19+
20+import Data.Maybe (fromJust)
21+import Data.Proxy (Proxy (..))
22+import Data.Typeable (Typeable)
23+import GHC.TypeLits
24+
25+import Data.TypeRep.Vector
26+
27+benchVector :: Benchmark
28+benchVector = bgroup "vector"
29+ [ bench "lookup" $ nf tenLookups bigMap
30+ -- , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)
31+ -- , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)
32+ ]
33+
34+tenLookups :: TypeRepVector (Proxy :: Nat -> *)
35+ -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
36+ , Proxy 50, Proxy 60, Proxy 70, Proxy 80
37+ )
38+tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
39+ where
40+ lp :: forall (a::Nat). Typeable a => Proxy a
41+ lp = fromJust $ lookup tmap
42+
43+-- TypeRepMap of 10000 elements
44+bigMap :: TypeRepVector (Proxy :: Nat -> *)
45+bigMap = fromList $ buildBigMap 10000 (Proxy :: Proxy 0) []
46+
47+data Z
48+data S a
49+
50+buildBigMap :: forall a . (Typeable a, KnownNat a) => Int -> Proxy (a :: Nat) -> [TF (Proxy :: Nat -> *)] -> [TF (Proxy :: Nat -> *)]
51+buildBigMap 1 x = (TF x :)
52+buildBigMap n x = (TF x :) . buildBigMap (n - 1) (Proxy :: Proxy (a + 1))
53+
54+-- rknf :: TypeRepMap f -> ()
55+-- rknf = rnf . keys
56+
57+type family BigProxy (n :: Nat) :: * where
58+ BigProxy 0 = Z
59+ BigProxy n = S (BigProxy (n - 1))
src/Data/TypeRep/OptimalVector.hsnew file+177
@@ -0,0 +1,177 @@
1+{-# OPTIONS_GHC -fno-warn-orphans #-}
2+
3+{-# LANGUAGE ExplicitForAll #-}
4+{-# LANGUAGE GADTs #-}
5+{-# LANGUAGE KindSignatures #-}
6+{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE PolyKinds #-}
8+{-# LANGUAGE ScopedTypeVariables #-}
9+{-# LANGUAGE TypeFamilies #-}
10+
11+
12+module Data.TypeRep.OptimalVector
13+ ( TypeRepVector (..)
14+ , TF (..)
15+ , empty
16+ , insert
17+ , lookup
18+ , size
19+ , fromList
20+ ) where
21+
22+import Prelude hiding (lookup)
23+
24+import Control.Arrow ((&&&))
25+import Data.Foldable (for_)
26+import Data.Proxy (Proxy (..))
27+import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
28+import Data.Word (Word64)
29+import GHC.Base (Any, liftM)
30+import GHC.Exts (sortWith)
31+import GHC.Fingerprint (Fingerprint (..))
32+import Unsafe.Coerce (unsafeCoerce)
33+
34+import qualified Data.Vector as V
35+import qualified Data.Vector.Generic as G
36+import qualified Data.Vector.Generic.Mutable as M
37+import qualified Data.Vector.Unboxed as Unboxed
38+
39+data instance Unboxed.MVector s Fingerprint = MFingerprintVectorOpt (Unboxed.MVector s Word64)
40+data instance Unboxed.Vector Fingerprint = FingerprintVectorOpt (Unboxed.Vector Word64)
41+
42+instance Unboxed.Unbox Fingerprint
43+
44+instance M.MVector Unboxed.MVector Fingerprint where
45+ {-# INLINE basicLength #-}
46+ basicLength (MFingerprintVectorOpt v) = M.basicLength v `div` 2
47+ {-# INLINE basicUnsafeSlice #-}
48+ basicUnsafeSlice i n (MFingerprintVectorOpt v) =
49+ MFingerprintVectorOpt $ M.basicUnsafeSlice (2 * i) (2 * n) v
50+ {-# INLINE basicOverlaps #-}
51+ basicOverlaps (MFingerprintVectorOpt v1) (MFingerprintVectorOpt v2) =
52+ M.basicOverlaps v1 v2
53+ {-# INLINE basicUnsafeNew #-}
54+ basicUnsafeNew n = MFingerprintVectorOpt `liftM` M.basicUnsafeNew (2 * n)
55+ {-# INLINE basicInitialize #-}
56+ basicInitialize (MFingerprintVectorOpt v) = M.basicInitialize v
57+ {-# INLINE basicUnsafeReplicate #-}
58+ basicUnsafeReplicate n_ (Fingerprint a b) = do
59+ v <- M.basicUnsafeNew $ 2 * n_
60+ for_ [0, 2 .. 2 * n_ - 1] $ \i -> do
61+ M.basicUnsafeWrite v i a
62+ M.basicUnsafeWrite v (i + 1) b
63+ return $ MFingerprintVectorOpt v
64+ {-# INLINE basicUnsafeRead #-}
65+ basicUnsafeRead (MFingerprintVectorOpt v) i = do
66+ a <- M.basicUnsafeRead v (2 * i)
67+ b <- M.basicUnsafeRead v (2 * i + 1)
68+ return (Fingerprint a b)
69+ {-# INLINE basicUnsafeWrite #-}
70+ basicUnsafeWrite (MFingerprintVectorOpt v) i (Fingerprint a b) = do
71+ M.basicUnsafeWrite v (2 * i) a
72+ M.basicUnsafeWrite v (2 * i + 1) b
73+ {-# INLINE basicClear #-}
74+ basicClear (MFingerprintVectorOpt v) = M.basicClear v
75+ {-# INLINE basicSet #-}
76+ basicSet (MFingerprintVectorOpt v) (Fingerprint a b) = do
77+ let n = M.basicLength v
78+ for_ [0, 2 .. n - 1] $ \i -> do
79+ M.basicUnsafeWrite v i a
80+ M.basicUnsafeWrite v (i + 1) b
81+ {-# INLINE basicUnsafeCopy #-}
82+ basicUnsafeCopy (MFingerprintVectorOpt v1) (MFingerprintVectorOpt v2) =
83+ M.basicUnsafeCopy v1 v2
84+ {-# INLINE basicUnsafeMove #-}
85+ basicUnsafeMove (MFingerprintVectorOpt v1) (MFingerprintVectorOpt v2) =
86+ M.basicUnsafeMove v1 v2
87+ {-# INLINE basicUnsafeGrow #-}
88+ basicUnsafeGrow (MFingerprintVectorOpt v) m_ =
89+ MFingerprintVectorOpt <$> M.basicUnsafeGrow v (2 * m_)
90+
91+instance G.Vector Unboxed.Vector Fingerprint where
92+ {-# INLINE basicUnsafeFreeze #-}
93+ basicUnsafeFreeze (MFingerprintVectorOpt v) =
94+ FingerprintVectorOpt <$> G.basicUnsafeFreeze v
95+ {-# INLINE basicUnsafeThaw #-}
96+ basicUnsafeThaw (FingerprintVectorOpt v) = do
97+ MFingerprintVectorOpt <$> G.basicUnsafeThaw v
98+ {-# INLINE basicLength #-}
99+ basicLength (FingerprintVectorOpt v) = G.basicLength v `div` 2
100+ {-# INLINE basicUnsafeSlice #-}
101+ basicUnsafeSlice i_ m_ (FingerprintVectorOpt v) =
102+ FingerprintVectorOpt (G.basicUnsafeSlice (2 * i_) (2 * m_) v)
103+ {-# INLINE basicUnsafeIndexM #-}
104+ basicUnsafeIndexM (FingerprintVectorOpt v) i_ = do
105+ a <- G.basicUnsafeIndexM v (2 * i_)
106+ b <- G.basicUnsafeIndexM v (2 * i_ + 1)
107+ return (Fingerprint a b)
108+ {-# INLINE basicUnsafeCopy #-}
109+ basicUnsafeCopy (MFingerprintVectorOpt v1) (FingerprintVectorOpt v2) =
110+ G.basicUnsafeCopy v1 v2
111+ {-# INLINE elemseq #-}
112+ elemseq _ (Fingerprint a b)
113+ = G.elemseq (undefined :: Unboxed.Vector a) a
114+ . G.elemseq (undefined :: Unboxed.Vector b) b
115+
116+data TypeRepVector f = TypeRepVect
117+ { fingerprints :: Unboxed.Vector Fingerprint
118+ , anys :: V.Vector Any
119+ }
120+
121+fromAny :: Any -> f a
122+fromAny = unsafeCoerce
123+
124+-- | Empty structure.
125+empty :: TypeRepVector f
126+empty = TypeRepVect mempty mempty
127+
128+-- | Inserts the value with its type as a key.
129+insert :: forall a f . Typeable a => a -> TypeRepVector f -> TypeRepVector f
130+insert = undefined
131+
132+-- | Looks up the value at the type.
133+-- >>> let x = lookup $ insert (11 :: Int) empty
134+-- >>> x :: Maybe Int
135+-- Just 11
136+-- >>> x :: Maybe ()
137+-- Nothing
138+lookup :: forall a f . Typeable a => TypeRepVector f -> Maybe (f a)
139+lookup tVect = fromAny . (anys tVect V.!)
140+ <$> binarySearch (typeRepFingerprint (typeRep (Proxy :: Proxy a))) (fingerprints tVect)
141+
142+-- | Returns the size of the 'TypeRepVect'.
143+size :: TypeRepVector f -> Int
144+size = Unboxed.length . fingerprints
145+
146+data TF f where
147+ TF :: Typeable a => f a -> TF f
148+
149+fromF :: Typeable a => f a -> Proxy a
150+fromF _ = Proxy
151+
152+fromList :: forall f . [TF f] -> TypeRepVector f
153+fromList tfs = TypeRepVect (Unboxed.fromList fps) (V.fromList ans)
154+ where
155+ (fps, ans) = unzip $ sortWith fst $ map (fp &&& an) tfs
156+
157+ fp :: TF f -> Fingerprint
158+ fp (TF x) = typeRepFingerprint $ typeRep $ fromF x
159+
160+ an :: TF f -> Any
161+ an (TF x) = unsafeCoerce x
162+
163+
164+-- | Returns the index is found.
165+binarySearch :: Fingerprint -> Unboxed.Vector Fingerprint -> Maybe Int
166+binarySearch fp fpVect =
167+ let ind = binSearchHelp (-1) (Unboxed.length fpVect) in
168+ if fp == (fpVect Unboxed.! ind) then Just ind else Nothing
169+ where
170+ binSearchHelp :: Int -> Int -> Int
171+ binSearchHelp l r = if l < r - 1
172+ then (
173+ let m = (l + r) `div` 2 in
174+ if fpVect Unboxed.! m < fp
175+ then binSearchHelp m r
176+ else binSearchHelp l m )
177+ else r
src/Data/TypeRep/Vector.hsnew file+188
@@ -0,0 +1,188 @@
1+{-# OPTIONS_GHC -fno-warn-orphans #-}
2+
3+{-# LANGUAGE ExplicitForAll #-}
4+{-# LANGUAGE GADTs #-}
5+{-# LANGUAGE KindSignatures #-}
6+{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE PolyKinds #-}
8+{-# LANGUAGE RankNTypes #-}
9+{-# LANGUAGE ScopedTypeVariables #-}
10+{-# LANGUAGE TypeFamilies #-}
11+
12+
13+module Data.TypeRep.Vector
14+ ( TypeRepVector (..)
15+ , TF (..)
16+ , empty
17+ , insert
18+ , lookup
19+ , size
20+ , fromList
21+ ) where
22+
23+import Prelude hiding (lookup)
24+
25+import Control.Arrow ((&&&))
26+import Data.Proxy (Proxy (..))
27+import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
28+import Data.Word (Word64)
29+import GHC.Base (Any)
30+import GHC.Exts (sortWith)
31+import GHC.Fingerprint (Fingerprint (..))
32+import Unsafe.Coerce (unsafeCoerce)
33+
34+import qualified Data.Vector as V
35+import qualified Data.Vector.Generic as G
36+import qualified Data.Vector.Generic.Mutable as M
37+import qualified Data.Vector.Unboxed as Unboxed
38+
39+data instance Unboxed.MVector s Fingerprint = MFingerprintVector (Unboxed.MVector s Word64) (Unboxed.MVector s Word64)
40+data instance Unboxed.Vector Fingerprint = FingerprintVector (Unboxed.Vector Word64) (Unboxed.Vector Word64)
41+
42+instance Unboxed.Unbox Fingerprint
43+
44+instance M.MVector Unboxed.MVector Fingerprint where
45+ {-# INLINE basicLength #-}
46+ basicLength (MFingerprintVector x _) = M.basicLength x
47+ {-# INLINE basicUnsafeSlice #-}
48+ basicUnsafeSlice i m (MFingerprintVector a b) =
49+ MFingerprintVector (M.basicUnsafeSlice i m a) (M.basicUnsafeSlice i m b)
50+ {-# INLINE basicOverlaps #-}
51+ basicOverlaps (MFingerprintVector as1 bs1) (MFingerprintVector as2 bs2) =
52+ M.basicOverlaps as1 as2 || M.basicOverlaps bs1 bs2
53+ {-# INLINE basicUnsafeNew #-}
54+ basicUnsafeNew n_ = do
55+ as <- M.basicUnsafeNew n_
56+ bs <- M.basicUnsafeNew n_
57+ return $ MFingerprintVector as bs
58+ {-# INLINE basicInitialize #-}
59+ basicInitialize (MFingerprintVector as bs) = do
60+ M.basicInitialize as
61+ M.basicInitialize bs
62+ {-# INLINE basicUnsafeReplicate #-}
63+ basicUnsafeReplicate n_ (Fingerprint a b) = do
64+ as <- M.basicUnsafeReplicate n_ a
65+ bs <- M.basicUnsafeReplicate n_ b
66+ return $ MFingerprintVector as bs
67+ {-# INLINE basicUnsafeRead #-}
68+ basicUnsafeRead (MFingerprintVector as bs) i_ = do
69+ a <- M.basicUnsafeRead as i_
70+ b <- M.basicUnsafeRead bs i_
71+ return (Fingerprint a b)
72+ {-# INLINE basicUnsafeWrite #-}
73+ basicUnsafeWrite (MFingerprintVector as bs) i_ (Fingerprint a b) = do
74+ M.basicUnsafeWrite as i_ a
75+ M.basicUnsafeWrite bs i_ b
76+ {-# INLINE basicClear #-}
77+ basicClear (MFingerprintVector as bs) = do
78+ M.basicClear as
79+ M.basicClear bs
80+ {-# INLINE basicSet #-}
81+ basicSet (MFingerprintVector as bs) (Fingerprint a b) = do
82+ M.basicSet as a
83+ M.basicSet bs b
84+ {-# INLINE basicUnsafeCopy #-}
85+ basicUnsafeCopy (MFingerprintVector as1 bs1) (MFingerprintVector as2 bs2) = do
86+ M.basicUnsafeCopy as1 as2
87+ M.basicUnsafeCopy bs1 bs2
88+ {-# INLINE basicUnsafeMove #-}
89+ basicUnsafeMove (MFingerprintVector as1 bs1) (MFingerprintVector as2 bs2) = do
90+ M.basicUnsafeMove as1 as2
91+ M.basicUnsafeMove bs1 bs2
92+ {-# INLINE basicUnsafeGrow #-}
93+ basicUnsafeGrow (MFingerprintVector as bs) m_ = do
94+ as' <- M.basicUnsafeGrow as m_
95+ bs' <- M.basicUnsafeGrow bs m_
96+ return $ MFingerprintVector as' bs'
97+
98+instance G.Vector Unboxed.Vector Fingerprint where
99+ {-# INLINE basicUnsafeFreeze #-}
100+ basicUnsafeFreeze (MFingerprintVector as bs) = do
101+ as' <- G.basicUnsafeFreeze as
102+ bs' <- G.basicUnsafeFreeze bs
103+ return $ FingerprintVector as' bs'
104+ {-# INLINE basicUnsafeThaw #-}
105+ basicUnsafeThaw (FingerprintVector as bs) = do
106+ as' <- G.basicUnsafeThaw as
107+ bs' <- G.basicUnsafeThaw bs
108+ return $ MFingerprintVector as' bs'
109+ {-# INLINE basicLength #-}
110+ basicLength (FingerprintVector x _) = G.basicLength x
111+ {-# INLINE basicUnsafeSlice #-}
112+ basicUnsafeSlice i_ m_ (FingerprintVector as bs) =
113+ FingerprintVector (G.basicUnsafeSlice i_ m_ as) (G.basicUnsafeSlice i_ m_ bs)
114+ {-# INLINE basicUnsafeIndexM #-}
115+ basicUnsafeIndexM (FingerprintVector as bs) i_ = do
116+ a <- G.basicUnsafeIndexM as i_
117+ b <- G.basicUnsafeIndexM bs i_
118+ return (Fingerprint a b)
119+ {-# INLINE basicUnsafeCopy #-}
120+ basicUnsafeCopy (MFingerprintVector as1 bs1) (FingerprintVector as2 bs2) = do
121+ G.basicUnsafeCopy as1 as2
122+ G.basicUnsafeCopy bs1 bs2
123+ {-# INLINE elemseq #-}
124+ elemseq _ (Fingerprint a b)
125+ = G.elemseq (undefined :: Unboxed.Vector a) a
126+ . G.elemseq (undefined :: Unboxed.Vector b) b
127+
128+data TypeRepVector f = TypeRepVect
129+ { fingerprints :: Unboxed.Vector Fingerprint
130+ , anys :: V.Vector Any
131+ }
132+
133+fromAny :: Any -> f a
134+fromAny = unsafeCoerce
135+
136+-- | Empty structure.
137+empty :: TypeRepVector f
138+empty = TypeRepVect mempty mempty
139+
140+-- | Inserts the value with its type as a key.
141+insert :: forall a f . Typeable a => a -> TypeRepVector f -> TypeRepVector f
142+insert = undefined
143+
144+-- | Looks up the value at the type.
145+-- >>> let x = lookup $ insert (11 :: Int) empty
146+-- >>> x :: Maybe Int
147+-- Just 11a Ty
148+-- >>> x :: Maybe ()
149+-- Nothing
150+lookup :: forall a f . Typeable a => TypeRepVector f -> Maybe (f a)
151+lookup tVect = fromAny . (anys tVect V.!)
152+ <$> binarySearch (typeRepFingerprint (typeRep (Proxy :: Proxy a))) (fingerprints tVect)
153+
154+-- | Returns the size of the 'TypeRepVect'.
155+size :: TypeRepVector f -> Int
156+size = Unboxed.length . fingerprints
157+
158+data TF f where
159+ TF :: Typeable a => f a -> TF f
160+
161+fromF :: Typeable a => f a -> Proxy a
162+fromF _ = Proxy
163+
164+fromList :: forall f . [TF f] -> TypeRepVector f
165+fromList tfs = TypeRepVect (Unboxed.fromList fps) (V.fromList ans)
166+ where
167+ (fps, ans) = unzip $ sortWith fst $ map (fp &&& an) tfs
168+
169+ fp :: TF f -> Fingerprint
170+ fp (TF x) = typeRepFingerprint $ typeRep $ fromF x
171+
172+ an :: TF f -> Any
173+ an (TF x) = unsafeCoerce x
174+
175+-- | Returns the index is found.
176+binarySearch :: Fingerprint -> Unboxed.Vector Fingerprint -> Maybe Int
177+binarySearch fp fpVect =
178+ let ind = binSearchHelp (-1) (Unboxed.length fpVect) in
179+ if fp == (fpVect Unboxed.! ind) then Just ind else Nothing
180+ where
181+ binSearchHelp :: Int -> Int -> Int
182+ binSearchHelp l r = if l < r - 1
183+ then (
184+ let m = (l + r) `div` 2 in
185+ if fpVect Unboxed.! m < fp
186+ then binSearchHelp m r
187+ else binSearchHelp l m )
188+ else r
test/Test/TypeRep/Vector.hsnew file+41
@@ -0,0 +1,41 @@
1+module Test.TypeRep.Vector where
2+
3+import Prelude hiding (lookup)
4+
5+import Data.Functor.Identity (Identity (..))
6+
7+import Test.Tasty.Hspec
8+
9+import Data.TypeRep.Vector
10+
11+-- Simple test for 'lookup', 'insert' and 'size' functions.
12+spec_insertLookup :: Spec
13+spec_insertLookup = do
14+ describe "Lookup Test" $ do
15+ it "returns the inserted element" $
16+ lookup (fromList [TF (Identity 'a')]) `shouldBe` Just (Identity 'a')
17+ it "returns the second inserted value of the same type" $
18+ lookup (fromList [TF (Identity 'b'), TF (Identity 'a')]) `shouldBe` Just (Identity 'b')
19+
20+-- describe "Size Test" $ do
21+-- it "is empty" $
22+-- size empty `shouldBe` 0
23+-- it "is of size 1 when 1 element inserted" $
24+-- size (insert (Identity 'a') empty) `shouldBe` 1
25+-- it "doesn't increase size when element of the same type is added" $
26+-- size (insert (Identity 'b') $ insert (Identity 'a') empty) `shouldBe` 1
27+-- it "returns 10 when 10 different types are inserted" $
28+-- size mapOf10 `shouldBe` 10
29+--
30+--
31+-- mapOf10 :: TypeRepMap Identity
32+-- mapOf10 = insert (Identity True)
33+-- $ insert (Identity [True, False])
34+-- $ insert (Identity $ Just True)
35+-- $ insert (Identity $ Just ())
36+-- $ insert (Identity [()])
37+-- $ insert (Identity ())
38+-- $ insert (Identity "aaa")
39+-- $ insert (Identity $ Just 'a')
40+-- $ insert (Identity 'a')
41+-- $ insert (Identity (11 :: Int)) empty
test/Test/TypeRep/VectorOpt.hsnew file+41
@@ -0,0 +1,41 @@
1+module Test.TypeRep.VectorOpt where
2+
3+import Prelude hiding (lookup)
4+
5+import Data.Functor.Identity (Identity (..))
6+
7+import Test.Tasty.Hspec
8+
9+import Data.TypeRep.OptimalVector
10+
11+-- Simple test for 'lookup', 'insert' and 'size' functions.
12+insertLookup :: Spec
13+insertLookup = do
14+ describe "Lookup Test" $ do
15+ it "returns the inserted element" $
16+ lookup (fromList [TF $ Identity 'a']) `shouldBe` Just (Identity 'a')
17+ it "returns the second inserted value of the same type" $
18+ lookup (fromList [TF (Identity 'b'), TF (Identity 'a')]) `shouldBe` Just (Identity 'b')
19+
20+-- describe "Size Test" $ do
21+-- it "is empty" $
22+-- size empty `shouldBe` 0
23+-- it "is of size 1 when 1 element inserted" $
24+-- size (insert (Identity 'a') empty) `shouldBe` 1
25+-- it "doesn't increase size when element of the same type is added" $
26+-- size (insert (Identity 'b') $ insert (Identity 'a') empty) `shouldBe` 1
27+-- it "returns 10 when 10 different types are inserted" $
28+-- size mapOf10 `shouldBe` 10
29+--
30+--
31+--mapOf10 :: TypeRepMap Identity
32+--mapOf10 = insert (Identity True)
33+-- $ insert (Identity [True, False])
34+-- $ insert (Identity $ Just True)
35+-- $ insert (Identity $ Just ())
36+-- $ insert (Identity [()])
37+-- $ insert (Identity ())
38+-- $ insert (Identity "aaa")
39+-- $ insert (Identity $ Just 'a')
40+-- $ insert (Identity 'a')
41+-- $ insert (Identity (11 :: Int)) empty
typerep-map.cabal+8
@@ -17,9 +17,12 @@ tested-with: GHC == 8.0.1
1717library
1818 hs-source-dirs: src
1919 exposed-modules: Data.TypeRep.Map
20+ , Data.TypeRep.Vector
21+ , Data.TypeRep.OptimalVector
2022 ghc-options: -Wall
2123 build-depends: base
2224 , containers
25+ , vector
2326 default-language: Haskell2010
2427
2528test-suite typerep-map-test
@@ -27,6 +30,8 @@ test-suite typerep-map-test
2730 hs-source-dirs: test
2831 main-is: Test.hs
2932 other-modules: Test.TypeRep.Map
33+ , Test.TypeRep.Vector
34+ , Test.TypeRep.VectorOpt
3035 build-depends: base
3136 , typerep-map
3237 , tasty
@@ -41,6 +46,9 @@ benchmark typerep-map-benchmark
4146 ghc-options: -Wall -Werror -O2 -threaded -rtsopts -with-rtsopts=-N -freduction-depth=0
4247 hs-source-dirs: benchmark
4348 main-is: Main.hs
49+ other-modules: Map
50+ , Vector
51+ , OptimalVector
4452 build-depends: base
4553 , criterion
4654 , typerep-map