typerep-map 0.3.0 → 0.3.1
raw patch · 13 files changed
+260/−114 lines, 13 filesdep +QuickCheckdep ~basedep ~containersdep ~criterionsetup-changed
Dependencies added: QuickCheck
Dependency ranges changed: base, containers, criterion, deepseq, dependent-map, dependent-sum, ghc-prim, ghc-typelits-knownnat, hedgehog, primitive, tasty, tasty-discover, tasty-hedgehog, tasty-hspec, vector
Files
- CHANGELOG.md +6/−0
- README.md +1/−1
- Setup.hs +0/−2
- benchmark/CMap.hs +34/−21
- benchmark/CacheMap.hs +35/−12
- benchmark/DMap.hs +36/−17
- benchmark/Main.hs +34/−18
- benchmark/OptimalVector.hs +16/−19
- benchmark/Spec.hs +53/−0
- src/Data/TypeRepMap/Internal.hs +8/−1
- typerep-extra-impls/Data/TypeRep/CMap.hs +4/−0
- typerep-extra-impls/Data/TypeRep/OptimalVector.hs +4/−0
- typerep-map.cabal +29/−23
CHANGELOG.md view
@@ -4,6 +4,12 @@ `typerep-map` uses [PVP Versioning][1]. The change log is available [on GitHub][2]. +# 0.3.1++* [#64](https://github.com/kowainik/typerep-map/issues/64):+ Fix segfault in `toList`.+* Support GHC 8.4.4 and 8.6.3.+ # 0.3.0 * [#46](https://github.com/kowainik/typerep-map/issues/46):
README.md view
@@ -7,7 +7,7 @@ `typerep-map` introduces `TMap` and `TypeRepMap` — data structures like [`Map`](http://hackage.haskell.org/package/containers-0.6.0.1/docs/Data-Map-Lazy.html#t:Map), but where types serve as keys, and values have the types specified in the corresponding key spots. -For the more details on the implementation see [this blog post](https://kowainik.github.io/posts/2018-07-11-typerep-map-step-by-step.html).+For the more details on the implementation see [this blog post](https://kowainik.github.io/posts/2018-07-11-typerep-map-step-by-step). ## Usage example
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
benchmark/CMap.hs view
@@ -9,29 +9,38 @@ {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} module CMap- ( benchMap- , prepareBenchMap+ ( spec ) where -import Criterion.Main (Benchmark, bench, bgroup, nf)+import Criterion.Main (bench, nf, env, whnf) import Prelude hiding (lookup) -import Control.DeepSeq (rnf)-import Control.Exception+import Spec import Data.Maybe (fromJust) import Data.Proxy (Proxy (..)) import Data.Typeable (Typeable) import GHC.TypeLits -import Data.TypeRep.CMap (TypeRepMap (..), empty, insert, keys, lookup)+import Data.TypeRep.CMap (TypeRepMap (..), empty, insert, lookup) -benchMap :: Benchmark-benchMap = bgroup "map"- [ bench "lookup" $ nf tenLookups bigMap- --, bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)- --, bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)- ]+spec :: BenchSpec+spec = BenchSpec+ { benchLookup = Just $ \name ->+ env (mkMap 10000) $ \ ~bigMap ->+ bench name $ nf tenLookups bigMap+ , benchInsertSmall = Just $ \name -> + bench name $ whnf (inserts empty 10) (Proxy @ 99999)+ , benchInsertBig = Just $ \name ->+ env (mkMap 10000) $ \ ~(bigMap) ->+ bench name $ whnf (inserts bigMap 1) (Proxy @ 99999)+ , benchUpdateSmall = Just $ \name ->+ env (mkMap 10) $ \ ~(smallMap) ->+ bench name $ whnf (inserts smallMap 10) (Proxy @ 0)+ , benchUpdateBig = Just $ \name ->+ env (mkMap 10000) $ \ ~(bigMap) ->+ bench name $ whnf (inserts bigMap 10) (Proxy @ 0)+ } tenLookups :: TypeRepMap (Proxy :: Nat -> *) -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40@@ -42,16 +51,20 @@ lp :: forall (a::Nat). Typeable a => Proxy a lp = fromJust $ lookup tmap --- TypeRepMap of 10000 elements-bigMap :: TypeRepMap (Proxy :: Nat -> *)-bigMap = buildBigMap 10000 (Proxy :: Proxy 0) empty+inserts :: forall a . (KnownNat a)+ => TypeRepMap (Proxy :: Nat -> *)+ -> Int+ -> Proxy (a :: Nat)+ -> TypeRepMap (Proxy :: Nat -> *)+inserts !c 0 _ = c+inserts !c n x = inserts+ (insert x c)+ (n-1)+ (Proxy :: Proxy (a+1)) +mkMap :: Int -> IO (TypeRepMap (Proxy :: Nat -> *))+mkMap n = pure $ buildBigMap n (Proxy :: Proxy 0) empty+ buildBigMap :: forall a . (KnownNat a) => Int -> Proxy (a :: Nat) -> TypeRepMap (Proxy :: Nat -> *) -> TypeRepMap (Proxy :: Nat -> *) buildBigMap 1 x = insert x buildBigMap n x = insert x . buildBigMap (n - 1) (Proxy :: Proxy (a + 1))--rknf :: TypeRepMap f -> ()-rknf = rnf . keys--prepareBenchMap :: IO ()-prepareBenchMap = evaluate (rknf bigMap)
benchmark/CacheMap.hs view
@@ -9,10 +9,11 @@ {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} module CacheMap- ( benchCacheMap+ ( spec ) where -import Criterion.Main (Benchmark, bench, bgroup, nf)+import Criterion.Main (bench, nf, whnf, env)+import Spec import Prelude hiding (lookup) @@ -22,14 +23,25 @@ import GHC.Exts (fromList) import GHC.TypeLits -import Data.TypeRepMap.Internal (TypeRepMap (..), WrapTypeable (..), lookup)+import Data.TypeRepMap.Internal (TypeRepMap (..), WrapTypeable (..), lookup, insert, empty) -benchCacheMap :: Benchmark-benchCacheMap = bgroup "vector optimal cache"- [ bench "lookup" $ nf tenLookups bigMap- -- , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)- -- , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)- ]+spec :: BenchSpec+spec = BenchSpec+ { benchLookup = Just $ \name ->+ env (mkMap 10000) $ \ ~bigMap ->+ bench name $ nf tenLookups bigMap+ , benchInsertSmall = Just $ \name -> + bench name $ whnf (inserts empty 10) (Proxy @ 99999)+ , benchInsertBig = Just $ \name ->+ env (mkMap 10000) $ \ ~(bigMap) ->+ bench name $ whnf (inserts bigMap 1) (Proxy @ 99999)+ , benchUpdateSmall = Just $ \name ->+ env (mkMap 10) $ \ ~(smallMap) ->+ bench name $ whnf (inserts smallMap 10) (Proxy @ 0)+ , benchUpdateBig = Just $ \name ->+ env (mkMap 10000) $ \ ~(bigMap) ->+ bench name $ whnf (inserts bigMap 10) (Proxy @ 0)+ } tenLookups :: TypeRepMap (Proxy :: Nat -> *) -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40@@ -40,9 +52,20 @@ lp :: forall (a::Nat). Typeable a => Proxy a lp = fromJust $ lookup tmap --- TypeRepMap of 10000 elements-bigMap :: TypeRepMap (Proxy :: Nat -> *)-bigMap = fromList $ buildBigMap 10000 (Proxy :: Proxy 0) []+inserts :: forall a . (KnownNat a)+ => TypeRepMap (Proxy :: Nat -> *)+ -> Int+ -> Proxy (a :: Nat)+ -> TypeRepMap (Proxy :: Nat -> *)+inserts !c 0 _ = c+inserts !c n x = inserts+ (insert x c)+ (n-1)+ (Proxy :: Proxy (a+1))++mkMap :: Int -> IO (TypeRepMap (Proxy :: Nat -> *))+mkMap n = pure $ fromList $ buildBigMap n (Proxy :: Proxy 0) []+ buildBigMap :: forall a . (KnownNat a) => Int
benchmark/DMap.hs view
@@ -11,16 +11,15 @@ {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver -fno-warn-orphans #-} module DMap- ( benchDMap- , prepareBenchDMap+ ( spec ) where -import Criterion.Main (Benchmark, bench, bgroup, nf)+import Criterion.Main (bench, nf, whnf, env) import Prelude hiding (lookup) -import Control.DeepSeq (rnf)-import Control.Exception+import Spec+import Control.DeepSeq (NFData(..)) import Data.Maybe (fromJust) import Data.Proxy (Proxy (..)) import Data.Type.Equality ((:~:) (..))@@ -35,13 +34,21 @@ type TypeRepMap = DMap TypeRep -benchDMap :: Benchmark-benchDMap = bgroup "dependent map"- [ bench "lookup" $ nf tenLookups bigMap- -- , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)- -- , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)- ] +spec :: BenchSpec+spec = BenchSpec+ { benchLookup = Just $ \name ->+ env mkBigMap $ \ ~(DMapNF bigMap) ->+ bench name $ nf tenLookups bigMap+ , benchInsertSmall = Just $ \name -> + bench name $ whnf (inserts empty 10) (Proxy @ 99999)+ , benchInsertBig = Just $ \name ->+ env mkBigMap $ \ ~(DMapNF bigMap) ->+ bench name $ whnf (inserts bigMap 1) (Proxy @ 99999)+ , benchUpdateSmall = Nothing -- Not implemented+ , benchUpdateBig = Nothing -- Not implemented+ }+ tenLookups :: TypeRepMap (Proxy :: Nat -> *) -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40 , Proxy 50, Proxy 60, Proxy 70, Proxy 80@@ -51,9 +58,20 @@ lp :: forall (a :: Nat) . Typeable a => Proxy a lp = fromJust $ lookup (typeRep @a) tmap +inserts :: forall a . (KnownNat a)+ => TypeRepMap (Proxy :: Nat -> *)+ -> Int+ -> Proxy (a :: Nat)+ -> TypeRepMap (Proxy :: Nat -> *)+inserts !c 0 _ = c+inserts !c n x = inserts+ (insert (typeRep @ a) x c)+ (n-1)+ (Proxy :: Proxy (a+1))+ -- TypeRepMap of 10000 elements-bigMap :: TypeRepMap (Proxy :: Nat -> *)-bigMap = buildBigMap 10000 (Proxy :: Proxy 0) empty+mkBigMap :: IO (DMapNF (Proxy :: Nat -> *))+mkBigMap = pure . DMapNF $ buildBigMap 10000 (Proxy :: Proxy 0) empty buildBigMap :: forall a . (KnownNat a) => Int@@ -64,11 +82,12 @@ buildBigMap n x = insert (typeRep @a) x . buildBigMap (n - 1) (Proxy @(a + 1)) -rknf :: TypeRepMap f -> ()-rknf = rnf . map (\(This t) -> typeRepFingerprint t) . keys+-- | Wrapper that provides NFData instance to the 'DMap' structure.+newtype DMapNF f = DMapNF (TypeRepMap f) -prepareBenchDMap :: IO ()-prepareBenchDMap = evaluate (rknf bigMap)+instance NFData (DMapNF f) where+ rnf (DMapNF x) = + rnf . map (\(This t) -> typeRepFingerprint t) $ keys x instance GEq TypeRep where geq :: TypeRep a -> TypeRep b -> Maybe (a :~: b)
benchmark/Main.hs view
@@ -2,30 +2,46 @@ module Main where -import Criterion.Main (defaultMain)+import Criterion.Main (defaultMain, bgroup) -import CacheMap (benchCacheMap)-import CMap (benchMap, prepareBenchMap)+import Spec+import qualified CMap+import qualified CacheMap #if ( __GLASGOW_HASKELL__ >= 802 )-import DMap (benchDMap, prepareBenchDMap)+import qualified DMap #endif-import OptimalVector (benchVectorOpt, prepareBenchVectorOpt)---import Vector (benchVector, prepareBenchVector)+import qualified OptimalVector as OptVec main :: IO () main = do- prepareBenchMap- --prepareBenchVector- prepareBenchVectorOpt+ let specs = [("CMap", CMap.spec)+ ,("CacheMap", CacheMap.spec) #if ( __GLASGOW_HASKELL__ >= 802 )- prepareBenchDMap+ , ("DMap", DMap.spec) #endif+ , ("OptVec", OptVec.spec)+ ]+ -- This code creates a benchmark group. Given a getter+ -- (that is test description) it gets a benchmark generation+ -- function from each module spec. Benchmark generation+ -- function takes a label and generate benchmarks. It's+ -- possible to introduce parameters passing in the same way.+ mkGroup getBenchmark = + [ mkBenchmark label+ | (label, spec) <- specs+ -- Here we use pure to force pattern matching in List+ -- then in case of pattern match failure `mzero` will+ -- be called, so benchmark will be ignored.+ , Just mkBenchmark <- pure $ getBenchmark spec+ ] defaultMain- [ benchMap- -- , benchVector- , benchCacheMap- , benchVectorOpt-#if ( __GLASGOW_HASKELL__ >= 802 )- , benchDMap-#endif- ]+ [ bgroup "lookup" $ mkGroup benchLookup + , bgroup "insert"+ [ bgroup "10 elements to empty" $ mkGroup benchInsertSmall+ , bgroup "1 element to big map" $ mkGroup benchInsertBig+ ]+ , bgroup "update"+ [ bgroup "10 elements to empty" $ mkGroup benchUpdateSmall+ , bgroup "1 element to big map" $ mkGroup benchUpdateBig+ ]+ ]
benchmark/OptimalVector.hs view
@@ -10,16 +10,14 @@ {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} module OptimalVector- ( benchVectorOpt- , prepareBenchVectorOpt+ ( spec ) where -import Criterion.Main (Benchmark, bench, bgroup, nf)+import Spec+import Criterion.Main (bench, nf, env) import Prelude hiding (lookup) -import Control.DeepSeq (rnf)-import Control.Exception import Data.Maybe (fromJust) import Data.Proxy (Proxy (..)) import Data.Typeable (Typeable)@@ -27,13 +25,17 @@ import Data.TypeRep.OptimalVector (TF (..), TypeRepMap (..), fromList, lookup) -benchVectorOpt :: Benchmark-benchVectorOpt = bgroup "vector optimal"- [ bench "lookup" $ nf tenLookups bigMap- -- , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)- -- , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)- ]-+spec :: BenchSpec+spec = BenchSpec+ { benchLookup = Just $ \name ->+ env mkBigMap $ \ ~bigMap ->+ bench name $ nf tenLookups bigMap+ , benchInsertSmall = Nothing -- Not implemented+ , benchInsertBig = Nothing -- Not implemented+ , benchUpdateSmall = Nothing -- Not implemented+ , benchUpdateBig = Nothing -- Not implemented+ }+ tenLookups :: TypeRepMap (Proxy :: Nat -> *) -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40 , Proxy 50, Proxy 60, Proxy 70, Proxy 80@@ -44,8 +46,8 @@ lp = fromJust $ lookup tmap -- TypeRepMap of 10000 elements-bigMap :: TypeRepMap (Proxy :: Nat -> *)-bigMap = fromList $ buildBigMap 10000 (Proxy :: Proxy 0) []+mkBigMap :: IO (TypeRepMap (Proxy :: Nat -> *))+mkBigMap = pure $ fromList $ buildBigMap 10000 (Proxy :: Proxy 0) [] buildBigMap :: forall a . (KnownNat a) => Int@@ -55,8 +57,3 @@ buildBigMap 1 x = (TF x :) buildBigMap n x = (TF x :) . buildBigMap (n - 1) (Proxy :: Proxy (a + 1)) -rknf :: TypeRepMap f -> ()-rknf tVect = rnf (fingerprintAs tVect, fingerprintBs tVect)--prepareBenchVectorOpt :: IO ()-prepareBenchVectorOpt = evaluate (rknf bigMap)
+ benchmark/Spec.hs view
@@ -0,0 +1,53 @@+-- | Specification of the benchmarks.+-- This module keeps a list of all bencharks, this way+-- we can group benchmark by the interesting function, not+-- by the implementation.+module Spec+ ( BenchSpec(..)+ ) where++import Criterion++-- | List of benchmarks that each module should provide.+-- If implementation can express the benchmark then it+-- can return @Nothing@ in that benchmark.+--+-- Map should contain elements from @1@ to @size of map@+-- inserted in ascending order (later that requirement may+-- change).+data BenchSpec = BenchSpec+ { benchLookup :: Maybe (String -> Benchmark)+ -- ^ Basic lookup we look 10 values inside 10k map.+ --+ -- Implementation may look like:+ -- @+ -- tenLookups :: TypeRepMap (Proxy :: Nat -> *)+ -- -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40+ -- , Proxy 50, Proxy 60, Proxy 70, Proxy 80+ -- )+ -- tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)+ -- @+ , benchInsertSmall :: Maybe (String -> Benchmark)+ -- ^ Insert 10 elements into an empty map.+ --+ -- Implementation may look like:+ -- @+ -- inserts :: forall a . (KnownNat a)+ -- => TypeRepMap (Proxy :: Nat -> *)+ -- -> Int+ -- -> Proxy (a :: Nat)+ -- -> TypeRepMap (Proxy :: Nat -> *)+ -- inserts !c 0 _ = c+ -- inserts !c n x = inserts (insert x c) (n-1) (Proxy :: Proxy (a+1))+ -- @+ , benchInsertBig :: Maybe (String -> Benchmark)+ -- ^ Insert 10 elements into a big map. Implementation is like+ -- a small map, but should insert values into 10k elements map.+ , benchUpdateSmall :: Maybe (String -> Benchmark)+ -- ^ Insert 10 elements into map of 10 elements, where each key+ -- was already inserted in the map+ , benchUpdateBig :: Maybe (String -> Benchmark)+ -- ^ Insert 10 elements into map of 10k elements, where each key+ -- was already inserted in the map+ }+
src/Data/TypeRepMap/Internal.hs view
@@ -25,6 +25,7 @@ import Control.Monad.ST (ST, runST) import Control.Monad.Zip (mzip)+import Control.DeepSeq import Data.Function (on) import Data.Kind (Type) import Data.List (intercalate, nubBy)@@ -74,6 +75,9 @@ } -- ^ an unsafe constructor for 'TypeRepMap' +instance NFData (TypeRepMap f) where+ rnf x = rnf (keys x) `seq` ()+ -- | Shows only keys. instance Show (TypeRepMap f) where show TypeRepMap{..} = "TypeRepMap [" ++ showKeys ++ "]"@@ -341,6 +345,9 @@ instance Show (WrapTypeable f) where show (WrapTypeable (_ :: f a)) = show $ calcFp @a +wrapTypeable :: TypeRep a -> f a -> WrapTypeable f+wrapTypeable tr = withTypeable tr WrapTypeable+ {- | prop> fromList . toList == 'id'@@ -371,7 +378,7 @@ toList = map toWrapTypeable . toTriples where toWrapTypeable :: (Fingerprint, Any, Any) -> WrapTypeable f- toWrapTypeable (_, an, k) = withTypeable (unsafeCoerce k) $ fromAny an+ toWrapTypeable (_, an, k) = wrapTypeable (unsafeCoerce k) (fromAny an) calcFp :: forall a . Typeable a => Fingerprint calcFp = typeRepFingerprint $ typeRep @a
typerep-extra-impls/Data/TypeRep/CMap.hs view
@@ -12,6 +12,7 @@ import Prelude hiding (lookup) +import Control.DeepSeq import Data.Proxy (Proxy (..)) import Data.Typeable (TypeRep, Typeable, typeRep) import GHC.Base (Any)@@ -23,6 +24,9 @@ newtype TypeRepMap (f :: k -> *) = TypeRepMap { unMap :: LMap.Map TypeRep Any }++instance NFData (TypeRepMap f) where+ rnf x = rnf (keys x) `seq` () -- | Empty structure. empty :: TypeRepMap f
typerep-extra-impls/Data/TypeRep/OptimalVector.hs view
@@ -23,6 +23,7 @@ import Prelude hiding (lookup) import Control.Arrow ((&&&))+import Control.DeepSeq import Data.Kind (Type) import Data.Proxy (Proxy (..)) import Data.Typeable (Typeable, typeRep, typeRepFingerprint)@@ -40,6 +41,9 @@ , fingerprintBs :: Unboxed.Vector Word64 , anys :: V.Vector Any }++instance NFData (TypeRepMap f) where+ rnf x = x `seq` () fromAny :: Any -> f a fromAny = unsafeCoerce
typerep-map.cabal view
@@ -1,5 +1,5 @@ name: typerep-map-version: 0.3.0+version: 0.3.1 synopsis: Efficient implementation of a dependent map with types as keys description: A dependent map from type representations to values of these types.@@ -22,14 +22,15 @@ license-file: LICENSE author: Kowainik, Vladislav Zavialov maintainer: xrom.xkov@gmail.com-copyright: 2017-2018 Kowainik+copyright: 2017-present Kowainik category: Data, Data Structures, Types build-type: Simple extra-doc-files: README.md , CHANGELOG.md cabal-version: 2.0 tested-with: GHC == 8.2.2- , GHC == 8.4.3+ , GHC == 8.4.4+ , GHC == 8.6.3 source-repository head type: git@@ -41,10 +42,11 @@ Data.TypeRepMap Data.TypeRepMap.Internal ghc-options: -Wall- build-depends: base >= 4.9 && < 5- , containers- , ghc-prim- , primitive >= 0.6.4+ build-depends: base >= 4.10 && < 5+ , containers >= 0.5.10.2 && < 0.7+ , ghc-prim ^>= 0.5.1.1+ , primitive ^>= 0.6.4+ , deepseq ^>= 1.4 default-extensions: OverloadedStrings RecordWildCards ScopedTypeVariables@@ -57,9 +59,10 @@ Data.TypeRep.OptimalVector Data.TypeRep.Vector ghc-options: -Wall- build-depends: base- , containers- , vector+ build-depends: base >= 4.10 && < 5+ , containers >= 0.5.10.2 && < 0.7+ , vector ^>= 0.12.0.1+ , deepseq ^>= 1.4 default-extensions: OverloadedStrings RecordWildCards ScopedTypeVariables@@ -76,15 +79,16 @@ , Test.TypeRep.MapProperty , Test.TypeRep.Vector , Test.TypeRep.VectorOpt- build-depends: base- , ghc-typelits-knownnat- , hedgehog+ build-depends: base >= 4.10 && < 5+ , ghc-typelits-knownnat >= 0.4.2 && < 0.7+ , hedgehog >= 0.5.3 && < 0.7 , typerep-map , typerep-extra-impls- , tasty- , tasty-discover >= 4.1.1- , tasty-hedgehog- , tasty-hspec+ , tasty >= 1.0.1.1 && < 1.3+ , tasty-discover >= 4.1.1 && < 4.3+ , tasty-hedgehog >= 0.1.0.2 && < 0.3+ , tasty-hspec ^>= 1.1.5+ , QuickCheck >= 2.11.3 && < 2.13 build-tool-depends: tasty-discover:tasty-discover ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N default-extensions: ScopedTypeVariables@@ -100,19 +104,21 @@ main-is: Main.hs other-modules: CMap , CacheMap+ , Spec , Vector , OptimalVector- build-depends: base- , criterion- , deepseq- , dependent-map- , dependent-sum- , ghc-typelits-knownnat+ build-depends: base >= 4.10 && < 5+ , criterion >= 1.4.1.0 && < 1.6+ , deepseq ^>= 1.4.3.0+ , dependent-map >= 0.2.4.0 && < 0.5+ , dependent-sum ^>= 0.4+ , ghc-typelits-knownnat >= 0.4.2 && < 0.7 , typerep-map , typerep-extra-impls default-extensions: OverloadedStrings RecordWildCards ScopedTypeVariables TypeApplications+ BangPatterns if impl(ghc >= 8.2.2) other-modules: DMap