1{-# OPTIONS_GHC -fno-warn-orphans #-}
3{-# LANGUAGE ExplicitForAll #-}
5{-# LANGUAGE KindSignatures #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE PolyKinds #-}
8{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE MagicHash, BangPatterns #-}
13module Data.TypeRep.OptimalVector
23import Prelude hiding (lookup)
25import Control.Arrow ((&&&))
26import Data.Foldable (for_)
27import Data.Proxy (Proxy (..))
28import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
29import Data.Word (Word64)
30import GHC.Base hiding (empty)
31import GHC.Exts (sortWith)
32import GHC.Fingerprint (Fingerprint (..))
33import Unsafe.Coerce (unsafeCoerce)
36import qualified Data.Vector as V
37import qualified Data.Vector.Generic as G
38import qualified Data.Vector.Generic.Mutable as M
39import qualified Data.Vector.Unboxed as Unboxed
41data instance Unboxed.MVector s Fingerprint = MFingerprintVectorOpt (Unboxed.MVector s Word64)
42data instance Unboxed.Vector Fingerprint = FingerprintVectorOpt (Unboxed.Vector Word64)
44instance Unboxed.Unbox Fingerprint
46instance M.MVector Unboxed.MVector Fingerprint where
47 {-# INLINE basicLength #-}
48 basicLength (MFingerprintVectorOpt v) = M.basicLength v `div` 2
49 {-# INLINE basicUnsafeSlice #-}
50 basicUnsafeSlice i n (MFingerprintVectorOpt v) =
51 MFingerprintVectorOpt $ M.basicUnsafeSlice (2 * i) (2 * n) v
52 {-# INLINE basicOverlaps #-}
53 basicOverlaps (MFingerprintVectorOpt v1) (MFingerprintVectorOpt v2) =
55 {-# INLINE basicUnsafeNew #-}
56 basicUnsafeNew n = MFingerprintVectorOpt `liftM` M.basicUnsafeNew (2 * n)
57 {-# INLINE basicInitialize #-}
58 basicInitialize (MFingerprintVectorOpt v) = M.basicInitialize v
59 {-# INLINE basicUnsafeReplicate #-}
60 basicUnsafeReplicate n_ (Fingerprint a b) = do
61 v <- M.basicUnsafeNew $ 2 * n_
62 for_ [0, 2 .. 2 * n_ - 1] $ \i -> do
63 M.basicUnsafeWrite v i a
64 M.basicUnsafeWrite v (i + 1) b
65 return $ MFingerprintVectorOpt v
66 {-# INLINE basicUnsafeRead #-}
67 basicUnsafeRead (MFingerprintVectorOpt v) i = do
68 a <- M.basicUnsafeRead v (2 * i)
69 b <- M.basicUnsafeRead v (2 * i + 1)
70 return (Fingerprint a b)
71 {-# INLINE basicUnsafeWrite #-}
72 basicUnsafeWrite (MFingerprintVectorOpt v) i (Fingerprint a b) = do
73 M.basicUnsafeWrite v (2 * i) a
74 M.basicUnsafeWrite v (2 * i + 1) b
75 {-# INLINE basicClear #-}
76 basicClear (MFingerprintVectorOpt v) = M.basicClear v
77 {-# INLINE basicSet #-}
78 basicSet (MFingerprintVectorOpt v) (Fingerprint a b) = do
79 let n = M.basicLength v
80 for_ [0, 2 .. n - 1] $ \i -> do
81 M.basicUnsafeWrite v i a
82 M.basicUnsafeWrite v (i + 1) b
83 {-# INLINE basicUnsafeCopy #-}
84 basicUnsafeCopy (MFingerprintVectorOpt v1) (MFingerprintVectorOpt v2) =
85 M.basicUnsafeCopy v1 v2
86 {-# INLINE basicUnsafeMove #-}
87 basicUnsafeMove (MFingerprintVectorOpt v1) (MFingerprintVectorOpt v2) =
88 M.basicUnsafeMove v1 v2
89 {-# INLINE basicUnsafeGrow #-}
90 basicUnsafeGrow (MFingerprintVectorOpt v) m_ =
91 MFingerprintVectorOpt <$> M.basicUnsafeGrow v (2 * m_)
93instance G.Vector Unboxed.Vector Fingerprint where
94 {-# INLINE basicUnsafeFreeze #-}
95 basicUnsafeFreeze (MFingerprintVectorOpt v) =
96 FingerprintVectorOpt <$> G.basicUnsafeFreeze v
97 {-# INLINE basicUnsafeThaw #-}
98 basicUnsafeThaw (FingerprintVectorOpt v) = do
99 MFingerprintVectorOpt <$> G.basicUnsafeThaw v
100 {-# INLINE basicLength #-}
101 basicLength (FingerprintVectorOpt v) = G.basicLength v `div` 2
102 {-# INLINE basicUnsafeSlice #-}
103 basicUnsafeSlice i_ m_ (FingerprintVectorOpt v) =
104 FingerprintVectorOpt (G.basicUnsafeSlice (2 * i_) (2 * m_) v)
105 {-# INLINE basicUnsafeIndexM #-}
106 basicUnsafeIndexM (FingerprintVectorOpt v) i_ = do
107 a <- G.basicUnsafeIndexM v (2 * i_)
108 b <- G.basicUnsafeIndexM v (2 * i_ + 1)
109 return (Fingerprint a b)
110 {-# INLINE basicUnsafeCopy #-}
111 basicUnsafeCopy (MFingerprintVectorOpt v1) (FingerprintVectorOpt v2) =
112 G.basicUnsafeCopy v1 v2
113 {-# INLINE elemseq #-}
114 elemseq _ (Fingerprint a b)
115 = G.elemseq (undefined :: Unboxed.Vector a) a
116 . G.elemseq (undefined :: Unboxed.Vector b) b
118data TypeRepVector f = TypeRepVect
119 { fingerprints :: Unboxed.Vector Fingerprint
120 , anys :: V.Vector Any
124fromAny = unsafeCoerce
127empty :: TypeRepVector f
128empty = TypeRepVect mempty mempty
130-- | Inserts the value with its type as a key.
131insert :: forall a f . Typeable a => a -> TypeRepVector f -> TypeRepVector f
134-- | Looks up the value at the type.
135-- >>> let x = lookup $ insert (11 :: Int) empty
140lookup :: forall a f . Typeable a => TypeRepVector f -> Maybe (f a)
141lookup tVect = fromAny . (anys tVect V.!)
142 <$> binarySearch (typeRepFingerprint (typeRep (Proxy :: Proxy a))) (fingerprints tVect)
144-- | Returns the size of the 'TypeRepVect'.
145size :: TypeRepVector f -> Int
146size = Unboxed.length . fingerprints
149 TF :: Typeable a => f a -> TF f
151fromF :: Typeable a => f a -> Proxy a
154fromList :: forall f . [TF f] -> TypeRepVector f
155fromList tfs = TypeRepVect (Unboxed.fromList fps) (V.fromList ans)
157 (fps, ans) = unzip $ sortWith fst $ map (fp &&& an) tfs
159 fp :: TF f -> Fingerprint
160 fp (TF x) = typeRepFingerprint $ typeRep $ fromF x
163 an (TF x) = unsafeCoerce x
165-- | Returns the index is found.
166binarySearch :: Fingerprint -> Unboxed.Vector Fingerprint -> Maybe Int
167binarySearch fp fpVect =
169 !(I# len) = Unboxed.length fpVect
170 ind = I# (binSearchHelp (-1#) len)
172 if fp == (fpVect Unboxed.! ind) then Just ind else Nothing
174 binSearchHelp :: Int# -> Int# -> Int#
175 binSearchHelp l r = case l <# (r -# 1#) of
178 let m = uncheckedIShiftRA# (l +# r) 1# in
179 if Unboxed.unsafeIndex fpVect (I# m) < fp
180 then binSearchHelp m r
181 else binSearchHelp l m
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list