on main help sign in
[#3] Attemp to impl Cached binary search (#11)

* [#3] Attemp to impl Cached binary search * Improve cached binary search * Make CacheMap main solution Move all others into internal folder Make CacheMap work without losing performance because of the moving out of the internal modules. * Inline lookup and binary search

commit43e8973e037aff42c78bb01d8fb5a964dd01eb5f authorVeronika Romashkina <vrom911@gmail.com> dateSat 7 Jul 2018, 16:43 (8 years ago) parent165949f
14 files changed+389−113
benchmark/Map.hs → benchmark/CMap.hs+1−1 benchmark/CacheMap.hs+58 benchmark/Main.hs+4−1 benchmark/OptimalVector.hs+1−1 src/Data/TypeRep/CMap.hs → internal/Data/TypeRep/CMap.hs internal/Data/TypeRep/CacheMap.hs+151 internal/Data/TypeRep/OptimalVector.hs+118 src/Data/TypeRep/Vector.hs → internal/Data/TypeRep/Vector.hs src/Data/TypeRep/Map.hs+1−101 stack.yaml+1−1 test/Test/TypeRep/Map.hs → test/Test/TypeRep/CMap.hs+1−1 test/Test/TypeRep/CacheMap.hs+41 test/Test/TypeRep/VectorOpt.hs+3−3 typerep-map.cabal+9−4
benchmark/Map.hs → benchmark/CMap.hsrenamed+1−1
@@ -8,7 +8,7 @@
88
99{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
1010
11−module Map
11+module CMap
1212 ( benchMap
1313 , prepareBenchMap
1414 ) where
benchmark/CacheMap.hsnew file+58
@@ -0,0 +1,58 @@
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 CacheMap
13+ ( benchCacheMap
14+ , prepareBenchCacheMap
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 Control.Exception
23+import Data.Maybe (fromJust)
24+import Data.Proxy (Proxy (..))
25+import Data.Typeable (Typeable)
26+import GHC.TypeLits
27+
28+import Data.TypeRep.Map (TF (..), TypeRepMap (..), fromList, lookup)
29+
30+benchCacheMap :: Benchmark
31+benchCacheMap = bgroup "vector optimal cache"
32+ [ bench "lookup" $ nf tenLookups bigMap
33+ -- , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)
34+ -- , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)
35+ ]
36+
37+tenLookups :: TypeRepMap (Proxy :: Nat -> *)
38+ -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
39+ , Proxy 50, Proxy 60, Proxy 70, Proxy 80
40+ )
41+tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
42+ where
43+ lp :: forall (a::Nat). Typeable a => Proxy a
44+ lp = fromJust $ lookup tmap
45+
46+-- TypeRepMap of 10000 elements
47+bigMap :: TypeRepMap (Proxy :: Nat -> *)
48+bigMap = fromList $ buildBigMap 10000 (Proxy :: Proxy 0) []
49+
50+buildBigMap :: forall 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 tVect = rnf (fingerprintAs tVect, fingerprintBs tVect)
56+
57+prepareBenchCacheMap :: IO ()
58+prepareBenchCacheMap = evaluate (rknf bigMap)
benchmark/Main.hs+4−1
@@ -2,17 +2,20 @@ module Main where
22
33import Criterion.Main (defaultMain)
44
5−import Map (benchMap, prepareBenchMap)
5+import CacheMap (benchCacheMap, prepareBenchCacheMap)
6+import CMap (benchMap, prepareBenchMap)
67import OptimalVector (benchVectorOpt, prepareBenchVectorOpt)
78--import Vector (benchVector, prepareBenchVector)
89
910main :: IO ()
1011main = do
1112 prepareBenchMap
13+ prepareBenchCacheMap
1214 --prepareBenchVector
1315 prepareBenchVectorOpt
1416 defaultMain
1517 [ benchMap
1618 -- , benchVector
19+ , benchCacheMap
1720 , benchVectorOpt
1821 ]
benchmark/OptimalVector.hs+1−1
@@ -25,7 +25,7 @@ import Data.Proxy (Proxy (..))
2525import Data.Typeable (Typeable)
2626import GHC.TypeLits
2727
28−import Data.TypeRep.Map (TF (..), TypeRepMap (..), fromList, lookup)
28+import Data.TypeRep.OptimalVector (TF (..), TypeRepMap (..), fromList, lookup)
2929
3030benchVectorOpt :: Benchmark
3131benchVectorOpt = bgroup "vector optimal"
src/Data/TypeRep/CMap.hs → internal/Data/TypeRep/CMap.hsrenamed

The content is the same.

internal/Data/TypeRep/CacheMap.hsnew file+151
@@ -0,0 +1,151 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE GADTs #-}
3+{-# LANGUAGE KindSignatures #-}
4+{-# LANGUAGE MagicHash #-}
5+{-# LANGUAGE PolyKinds #-}
6+{-# LANGUAGE TypeFamilies #-}
7+
8+-- {-# OPTIONS_GHC -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes #-}
9+
10+module Data.TypeRep.CacheMap
11+ ( -- * Map type
12+ TypeRepMap (..)
13+
14+ -- 'TypeRepMap' interface
15+ , empty
16+ , insert
17+ , lookup
18+ , size
19+
20+ -- * Helpful testing functions
21+ , TF (..)
22+ , fromList
23+ ) where
24+
25+import Prelude hiding (lookup)
26+
27+import Control.Arrow ((&&&))
28+import Data.Kind (Type)
29+import Data.Proxy (Proxy (..))
30+import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
31+import Data.Word (Word64)
32+import GHC.Base (Any, Int (..), Int#, (*#), (+#), (<#))
33+import GHC.Exts (inline, sortWith)
34+import GHC.Fingerprint (Fingerprint (..))
35+import GHC.Prim (eqWord#, ltWord#)
36+import GHC.Word (Word64 (..))
37+import Unsafe.Coerce (unsafeCoerce)
38+
39+import qualified Data.Vector as V
40+import qualified Data.Vector.Unboxed as Unboxed
41+
42+data TypeRepMap (f :: k -> Type) = TypeRepMap
43+ { fingerprintAs :: Unboxed.Vector Word64
44+ , fingerprintBs :: Unboxed.Vector Word64
45+ , anys :: V.Vector Any
46+ }
47+
48+fromAny :: Any -> f a
49+fromAny = unsafeCoerce
50+
51+-- | Empty structure.
52+empty :: TypeRepMap f
53+empty = TypeRepMap mempty mempty mempty
54+
55+-- | Inserts the value with its type as a key.
56+insert :: forall a f . Typeable a => a -> TypeRepMap f -> TypeRepMap f
57+insert = undefined
58+
59+-- | Looks up the value at the type.
60+-- >>> let x = lookup $ insert (11 :: Int) empty
61+-- >>> x :: Maybe Int
62+-- Just 11
63+-- >>> x :: Maybe ()
64+-- Nothing
65+lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
66+lookup tVect = fromAny . (anys tVect V.!)
67+ <$> cachedBinarySearch (typeRepFingerprint $ typeRep $ Proxy @a)
68+ (fingerprintAs tVect)
69+ (fingerprintBs tVect)
70+{-# INLINE lookup #-}
71+
72+-- | Returns the size of the 'TypeRepMap'.
73+size :: TypeRepMap f -> Int
74+size = Unboxed.length . fingerprintAs
75+
76+-- | Binary searched based on this article
77+-- http://bannalia.blogspot.com/2015/06/cache-friendly-binary-search.html
78+-- with modification for our two-vector search case.
79+cachedBinarySearch :: Fingerprint -> Unboxed.Vector Word64 -> Unboxed.Vector Word64 -> Maybe Int
80+cachedBinarySearch (Fingerprint (W64# a) (W64# b)) fpAs fpBs = inline (go 0#)
81+ where
82+ go :: Int# -> Maybe Int
83+ go i = case i <# len of
84+ 0# -> Nothing
85+ _ -> let !(W64# valA) = Unboxed.unsafeIndex fpAs (I# i) in case a `ltWord#` valA of
86+ 0# -> case a `eqWord#` valA of
87+ 0# -> go (2# *# i +# 2#)
88+ _ -> let !(W64# valB) = Unboxed.unsafeIndex fpBs (I# i) in case b `eqWord#` valB of
89+ 0# -> case b `ltWord#` valB of
90+ 0# -> go (2# *# i +# 2#)
91+ _ -> go (2# *# i +# 1#)
92+ _ -> Just (I# i)
93+ _ -> go (2# *# i +# 1#)
94+
95+ len :: Int#
96+ len = let !(I# l) = Unboxed.length fpAs in l
97+{-# INLINE cachedBinarySearch #-}
98+
99+----------------------------------------------------------------------------
100+-- Functions for testing and benchmarking
101+----------------------------------------------------------------------------
102+
103+data TF f where
104+ TF :: Typeable a => f a -> TF f
105+
106+fromF :: Typeable a => f a -> Proxy a
107+fromF _ = Proxy
108+
109+fromList :: forall f . [TF f] -> TypeRepMap f
110+fromList tfs = TypeRepMap (Unboxed.fromList fpAs) (Unboxed.fromList fpBs) (V.fromList ans)
111+ where
112+ (fpAs, fpBs) = unzip $ fmap (\(Fingerprint a b) -> (a, b)) fps
113+ (fps, ans) = unzip $ breadthFirst $ fromListToTree $ sortWith fst $ map (fp &&& an) tfs
114+
115+ fp :: TF f -> Fingerprint
116+ fp (TF x) = typeRepFingerprint $ typeRep $ fromF x
117+
118+ an :: TF f -> Any
119+ an (TF x) = unsafeCoerce x
120+
121+----------------------------------------------------------------------------
122+-- Tree
123+----------------------------------------------------------------------------
124+
125+data Tree a = Leaf | Node a (Tree a) (Tree a)
126+ deriving (Show)
127+
128+fromListToTree :: [a] -> Tree a
129+fromListToTree [] = Leaf
130+fromListToTree xs =
131+ let len = length xs
132+ in case splitAt (len `div` 2) xs of
133+ ([], []) -> Leaf
134+ (ls, []) -> Node (last ls) (fromListToTree $ init ls) Leaf
135+ ([], (r:rs)) -> Node r Leaf $ fromListToTree rs
136+ (ls, r:rs) -> Node r (fromListToTree ls) (fromListToTree rs)
137+
138+breadthFirst :: Tree a -> [a]
139+breadthFirst tree = bf [tree]
140+ where
141+ bf :: [Tree a] -> [a]
142+ bf [] = []
143+ bf xs = mapValue xs ++ bf (concatMap children xs)
144+
145+ mapValue :: [Tree a] -> [a]
146+ mapValue [] = []
147+ mapValue (Leaf : xs) = mapValue xs
148+ mapValue (Node a _ _ : xs) = a : mapValue xs
149+
150+ children Leaf = []
151+ children (Node _ l r) = [l, r]
internal/Data/TypeRep/OptimalVector.hsnew file+118
@@ -0,0 +1,118 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE GADTs #-}
3+{-# LANGUAGE KindSignatures #-}
4+{-# LANGUAGE MagicHash #-}
5+{-# LANGUAGE PolyKinds #-}
6+{-# LANGUAGE TypeFamilies #-}
7+
8+module Data.TypeRep.OptimalVector
9+ ( -- * Map type
10+ TypeRepMap (..)
11+
12+ -- 'TypeRepMap' interface
13+ , empty
14+ , insert
15+ , lookup
16+ , size
17+
18+ -- * Helpful testing functions
19+ , TF (..)
20+ , fromList
21+ ) where
22+
23+import Prelude hiding (lookup)
24+
25+import Control.Arrow ((&&&))
26+import Data.Kind (Type)
27+import Data.Proxy (Proxy (..))
28+import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
29+import Data.Word (Word64)
30+import GHC.Base (Any, Int (..), Int#, uncheckedIShiftRA#, (+#), (-#), (<#))
31+import GHC.Exts (inline, sortWith)
32+import GHC.Fingerprint (Fingerprint (..))
33+import Unsafe.Coerce (unsafeCoerce)
34+
35+import qualified Data.Vector as V
36+import qualified Data.Vector.Unboxed as Unboxed
37+
38+data TypeRepMap (f :: k -> Type) = TypeRepMap
39+ { fingerprintAs :: Unboxed.Vector Word64
40+ , fingerprintBs :: Unboxed.Vector Word64
41+ , anys :: V.Vector Any
42+ }
43+
44+fromAny :: Any -> f a
45+fromAny = unsafeCoerce
46+
47+-- | Empty structure.
48+empty :: TypeRepMap f
49+empty = TypeRepMap mempty mempty mempty
50+
51+-- | Inserts the value with its type as a key.
52+insert :: forall a f . Typeable a => a -> TypeRepMap f -> TypeRepMap f
53+insert = undefined
54+
55+-- | Looks up the value at the type.
56+-- >>> let x = lookup $ insert (11 :: Int) empty
57+-- >>> x :: Maybe Int
58+-- Just 11
59+-- >>> x :: Maybe ()
60+-- Nothing
61+lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
62+lookup tVect = fromAny . (anys tVect V.!)
63+ <$> binarySearch (typeRepFingerprint $ typeRep $ Proxy @a)
64+ (fingerprintAs tVect)
65+ (fingerprintBs tVect)
66+
67+-- | Returns the size of the 'TypeRepMap'.
68+size :: TypeRepMap f -> Int
69+size = Unboxed.length . fingerprintAs
70+
71+-- | Returns the index is found.
72+binarySearch :: Fingerprint -> Unboxed.Vector Word64 -> Unboxed.Vector Word64 -> Maybe Int
73+binarySearch (Fingerprint a b) fpAs fpBs =
74+ let
75+ !(I# len) = Unboxed.length fpAs
76+ checkfpBs :: Int# -> Maybe Int
77+ checkfpBs i =
78+ case i <# len of
79+ 0# -> Nothing
80+ _ ->
81+ if a /= Unboxed.unsafeIndex fpAs (I# i)
82+ then Nothing
83+ else if b == Unboxed.unsafeIndex fpBs (I# i)
84+ then Just (I# i)
85+ else checkfpBs (i +# 1#)
86+ in
87+ inline (checkfpBs (binSearchHelp (-1#) len))
88+ where
89+ binSearchHelp :: Int# -> Int# -> Int#
90+ binSearchHelp l r = case l <# (r -# 1#) of
91+ 0# -> r
92+ _ ->
93+ let m = uncheckedIShiftRA# (l +# r) 1# in
94+ if Unboxed.unsafeIndex fpAs (I# m) < a
95+ then binSearchHelp m r
96+ else binSearchHelp l m
97+
98+----------------------------------------------------------------------------
99+-- Functions for testing and benchmarking
100+----------------------------------------------------------------------------
101+
102+data TF f where
103+ TF :: Typeable a => f a -> TF f
104+
105+fromF :: Typeable a => f a -> Proxy a
106+fromF _ = Proxy
107+
108+fromList :: forall f . [TF f] -> TypeRepMap f
109+fromList tfs = TypeRepMap (Unboxed.fromList fpAs) (Unboxed.fromList fpBs) (V.fromList ans)
110+ where
111+ (fpAs, fpBs) = unzip $ fmap (\(Fingerprint a b) -> (a, b)) fps
112+ (fps, ans) = unzip $ sortWith fst $ map (fp &&& an) tfs
113+
114+ fp :: TF f -> Fingerprint
115+ fp (TF x) = typeRepFingerprint $ typeRep $ fromF x
116+
117+ an :: TF f -> Any
118+ an (TF x) = unsafeCoerce x
src/Data/TypeRep/Vector.hs → internal/Data/TypeRep/Vector.hsrenamed

The content is the same.

src/Data/TypeRep/Map.hs+1−101
@@ -1,10 +1,3 @@
1−{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE GADTs #-}
3−{-# LANGUAGE KindSignatures #-}
4−{-# LANGUAGE MagicHash #-}
5−{-# LANGUAGE PolyKinds #-}
6−{-# LANGUAGE TypeFamilies #-}
7−
81module Data.TypeRep.Map
92 ( -- * Map type
103 TypeRepMap (..)
@@ -22,97 +15,4 @@ module Data.TypeRep.Map
2215
2316import Prelude hiding (lookup)
2417
25−import Control.Arrow ((&&&))
26−import Data.Kind (Type)
27−import Data.Proxy (Proxy (..))
28−import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
29−import Data.Word (Word64)
30−import GHC.Base (Any, Int (..), Int#, uncheckedIShiftRA#, (+#), (-#), (<#))
31−import GHC.Exts (inline, sortWith)
32−import GHC.Fingerprint (Fingerprint (..))
33−import Unsafe.Coerce (unsafeCoerce)
34−
35−import qualified Data.Vector as V
36−import qualified Data.Vector.Unboxed as Unboxed
37−
38−data TypeRepMap (f :: k -> Type) = TypeRepMap
39− { fingerprintAs :: Unboxed.Vector Word64
40− , fingerprintBs :: Unboxed.Vector Word64
41− , anys :: V.Vector Any
42− }
43−
44−fromAny :: Any -> f a
45−fromAny = unsafeCoerce
46−
47−-- | Empty structure.
48−empty :: TypeRepMap f
49−empty = TypeRepMap mempty mempty mempty
50−
51−-- | Inserts the value with its type as a key.
52−insert :: forall a f . Typeable a => a -> TypeRepMap f -> TypeRepMap f
53−insert = undefined
54−
55−-- | Looks up the value at the type.
56−-- >>> let x = lookup $ insert (11 :: Int) empty
57−-- >>> x :: Maybe Int
58−-- Just 11
59−-- >>> x :: Maybe ()
60−-- Nothing
61−lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
62−lookup tVect = fromAny . (anys tVect V.!)
63− <$> binarySearch (typeRepFingerprint $ typeRep $ Proxy @a)
64− (fingerprintAs tVect)
65− (fingerprintBs tVect)
66−
67−-- | Returns the size of the 'TypeRepMap'.
68−size :: TypeRepMap f -> Int
69−size = Unboxed.length . fingerprintAs
70−
71−-- | Returns the index is found.
72−binarySearch :: Fingerprint -> Unboxed.Vector Word64 -> Unboxed.Vector Word64 -> Maybe Int
73−binarySearch (Fingerprint a b) fpAs fpBs =
74− let
75− !(I# len) = Unboxed.length fpAs
76− checkfpBs :: Int# -> Maybe Int
77− checkfpBs i =
78− case i <# len of
79− 0# -> Nothing
80− _ ->
81− if a /= Unboxed.unsafeIndex fpAs (I# i)
82− then Nothing
83− else if b == Unboxed.unsafeIndex fpBs (I# i)
84− then Just (I# i)
85− else checkfpBs (i +# 1#)
86− in
87− inline (checkfpBs (binSearchHelp (-1#) len))
88− where
89− binSearchHelp :: Int# -> Int# -> Int#
90− binSearchHelp l r = case l <# (r -# 1#) of
91− 0# -> r
92− _ ->
93− let m = uncheckedIShiftRA# (l +# r) 1# in
94− if Unboxed.unsafeIndex fpAs (I# m) < a
95− then binSearchHelp m r
96− else binSearchHelp l m
97−
98−----------------------------------------------------------------------------
99−-- Functions for testing and benchmarking
100−----------------------------------------------------------------------------
101−
102−data TF f where
103− TF :: Typeable a => f a -> TF f
104−
105−fromF :: Typeable a => f a -> Proxy a
106−fromF _ = Proxy
107−
108−fromList :: forall f . [TF f] -> TypeRepMap f
109−fromList tfs = TypeRepMap (Unboxed.fromList fpAs) (Unboxed.fromList fpBs) (V.fromList ans)
110− where
111− (fpAs, fpBs) = unzip $ fmap (\(Fingerprint a b) -> (a, b)) fps
112− (fps, ans) = unzip $ sortWith fst $ map (fp &&& an) tfs
113−
114− fp :: TF f -> Fingerprint
115− fp (TF x) = typeRepFingerprint $ typeRep $ fromF x
116−
117− an :: TF f -> Any
118− an (TF x) = unsafeCoerce x
18+import Data.TypeRep.CacheMap
stack.yaml+1−1
@@ -1 +1 @@
1−resolver: lts-11.15
1+resolver: nightly-2018-07-05
test/Test/TypeRep/Map.hs → test/Test/TypeRep/CMap.hsrenamed+1−1
@@ -1,4 +1,4 @@
1−module Test.TypeRep.Map where
1+module Test.TypeRep.CMap where
22
33import Prelude hiding (lookup)
44
test/Test/TypeRep/CacheMap.hsnew file+41
@@ -0,0 +1,41 @@
1+module Test.TypeRep.CacheMap 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.CacheMap (TF (..), fromList, lookup)
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.hs+3−3
@@ -6,11 +6,11 @@ import Data.Functor.Identity (Identity (..))
66
77import Test.Tasty.Hspec
88
9−import Data.TypeRep.Map (TF (..), fromList, lookup)
9+import Data.TypeRep.OptimalVector (TF (..), fromList, lookup)
1010
1111-- Simple test for 'lookup', 'insert' and 'size' functions.
12−insertLookup :: Spec
13−insertLookup = do
12+spec_insertLookup :: Spec
13+spec_insertLookup = do
1414 describe "Lookup Test" $ do
1515 it "returns the inserted element" $
1616 lookup (fromList [TF $ Identity 'a']) `shouldBe` Just (Identity 'a')
typerep-map.cabal+9−4
@@ -21,7 +21,7 @@ library
2121 exposed-modules: Data.TypeRep.Map
2222 ghc-options: -Wall
2323 build-depends: base
24− , vector
24+ , typerep-map-internal -any
2525 default-extensions: OverloadedStrings
2626 RecordWildCards
2727 ScopedTypeVariables
@@ -29,12 +29,15 @@ library
2929 default-language: Haskell2010
3030
3131library typerep-map-internal
32− hs-source-dirs: src
32+ hs-source-dirs: internal
3333 exposed-modules: Data.TypeRep.CMap
34+ Data.TypeRep.CacheMap
35+ Data.TypeRep.OptimalVector
3436 Data.TypeRep.Vector
3537 ghc-options: -Wall
3638 build-depends: base
3739 , containers
40+ , ghc-prim
3841 , vector
3942 default-extensions: OverloadedStrings
4043 RecordWildCards
@@ -47,7 +50,8 @@ test-suite typerep-map-test
4750 type: exitcode-stdio-1.0
4851 hs-source-dirs: test
4952 main-is: Test.hs
50− other-modules: Test.TypeRep.Map
53+ other-modules: Test.TypeRep.CMap
54+ , Test.TypeRep.CacheMap
5155 , Test.TypeRep.Vector
5256 , Test.TypeRep.VectorOpt
5357 build-depends: base
@@ -66,7 +70,8 @@ benchmark typerep-map-benchmark
6670 ghc-options: -Wall -O2 -threaded -rtsopts -with-rtsopts=-N -freduction-depth=0
6771 hs-source-dirs: benchmark
6872 main-is: Main.hs
69− other-modules: Map
73+ other-modules: CMap
74+ , CacheMap
7075 , Vector
7176 , OptimalVector
7277 build-depends: base