TrieMap 1.5.0 → 2.0.0
raw patch · 35 files changed
+1806/−1278 lines, 35 filesdep +primitivedep +vectordep −array
Dependencies added: primitive, vector
Dependencies removed: array
Files
- Data/TrieMap.hs +59/−37
- Data/TrieMap/Class.hs +9/−6
- Data/TrieMap/Class/Instances.hs +2/−4
- Data/TrieMap/IntMap.hs +107/−122
- Data/TrieMap/Key.hs +25/−15
- Data/TrieMap/Modifiers.hs +1/−12
- Data/TrieMap/OrdMap.hs +81/−85
- Data/TrieMap/ProdMap.hs +34/−34
- Data/TrieMap/RadixTrie.hs +94/−233
- Data/TrieMap/RadixTrie/Edge.hs +269/−0
- Data/TrieMap/RadixTrie/Slice.hs +48/−0
- Data/TrieMap/Rep.hs +0/−25
- Data/TrieMap/Rep/Instances.hs +0/−188
- Data/TrieMap/Rep/TH.hs +0/−38
- Data/TrieMap/Representation.hs +3/−40
- Data/TrieMap/Representation/Class.hs +16/−0
- Data/TrieMap/Representation/Instances.hs +50/−0
- Data/TrieMap/Representation/Instances/Basic.hs +39/−0
- Data/TrieMap/Representation/Instances/ByteString.hs +21/−0
- Data/TrieMap/Representation/Instances/Foreign.hs +27/−0
- Data/TrieMap/Representation/Instances/Prim.hs +52/−0
- Data/TrieMap/Representation/Instances/Vectors.hs +130/−0
- Data/TrieMap/Representation/TH.hs +107/−134
- Data/TrieMap/Representation/TH/Factorized.hs +76/−0
- Data/TrieMap/Representation/TH/ReprMonad.hs +82/−0
- Data/TrieMap/Representation/TH/Representation.hs +127/−0
- Data/TrieMap/Representation/TH/Utils.hs +80/−0
- Data/TrieMap/ReverseMap.hs +45/−46
- Data/TrieMap/Sized.hs +10/−1
- Data/TrieMap/TrieKey.hs +0/−135
- Data/TrieMap/UnionMap.hs +133/−81
- Data/TrieMap/UnitMap.hs +18/−17
- Data/TrieMap/Utils.hs +17/−0
- Tests.hs +13/−8
- TrieMap.cabal +31/−17
Data/TrieMap.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TypeFamilies, FlexibleContexts, UnboxedTuples #-}+{-# LANGUAGE TypeFamilies, FlexibleContexts, UnboxedTuples, RecordWildCards #-} module Data.TrieMap ( -- * Map type@@ -129,8 +129,8 @@ import Data.TrieMap.Class.Instances() import Data.TrieMap.TrieKey import Data.TrieMap.Applicative-import Data.TrieMap.Rep-import Data.TrieMap.Rep.Instances ()+import Data.TrieMap.Representation+import Data.TrieMap.Representation.Instances () import Data.TrieMap.Sized import Control.Applicative hiding (empty)@@ -161,32 +161,38 @@ -- -- 1. A 'TLocation' (and the value at that position, if any) is obtained from a 'TMap' by searching or indexing. -- 2. A new 'TMap' is made from a 'TLocation' by either filling the hole with a value ('assign') or erasing it ('clear').-newtype TLocation k a = TLoc (Hole (Rep k) (Elem a))+data TLocation k a = TLoc k (Hole (Rep k) (Assoc k a)) +{-# INLINE empty #-} -- | /O(1)/. The empty map. empty :: TKey k => TMap k a empty = TMap emptyM -- | /O(1)/. A map with a single element.+{-# INLINE singleton #-} singleton :: TKey k => k -> a -> TMap k a-singleton k a = insert k a empty+singleton k a = TMap (singletonM (toRep k) (Assoc k a)) -- | /O(1)/. Is the map empty?+{-# INLINE null #-} null :: TKey k => TMap k a -> Bool null (TMap m) = nullM m -- | Lookup the value at a key in the map. -- -- The function will return the corresponding value as @('Just' value)@, or 'Nothing' if the key isn't in the map.+{-# INLINE lookup #-} lookup :: TKey k => k -> TMap k a -> Maybe a-lookup k (TMap m) = getElem <$> lookupM (toRep k) m+lookup k (TMap m) = getValue <$> lookupM (toRep k) m -- | The expression @('findWithDefault' def k map)@ returns the value at key @k@ or returns default value @def@ -- when the key is not in the map.+{-# INLINE findWithDefault #-} findWithDefault :: TKey k => a -> k -> TMap k a -> a findWithDefault a = fromMaybe a .: lookup -- | Find the value at a key. Calls 'error' when the element can not be found.+{-# INLINE (!) #-} (!) :: TKey k => TMap k a -> k -> a m ! k = fromMaybe (error "Element not found") (lookup k m) @@ -299,6 +305,7 @@ -- > update f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "new a")] -- > update f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")] -- > update f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"+{-# INLINE update #-} update :: TKey k => (a -> Maybe a) -> k -> TMap k a -> TMap k a update f = updateWithKey (const f) @@ -311,6 +318,7 @@ -- > updateWithKey f 5 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:new a")] -- > updateWithKey f 7 (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a")] -- > updateWithKey f 3 (fromList [(5,"a"), (3,"b")]) == singleton 5 "a"+{-# INLINE updateWithKey #-} updateWithKey :: TKey k => (k -> a -> Maybe a) -> k -> TMap k a -> TMap k a updateWithKey f k m = case search k m of (Nothing, _) -> m@@ -318,17 +326,20 @@ -- | Post-order fold. The function will be applied from the lowest -- value to the highest.+{-# INLINE foldrWithKey #-} foldrWithKey :: TKey k => (k -> a -> b -> b) -> b -> TMap k a -> b-foldrWithKey f z (TMap m) = foldrWithKeyM (\ k (Elem a) -> f (fromRep k) a) m z+foldrWithKey f z (TMap m) = foldrM (\ (Assoc k a) -> f k a) m z -- | Pre-order fold. The function will be applied from the highest -- value to the lowest.+{-# INLINE foldlWithKey #-} foldlWithKey :: TKey k => (b -> k -> a -> b) -> b -> TMap k a -> b-foldlWithKey f z (TMap m) = foldlWithKeyM (\ k z (Elem a) -> f z (fromRep k) a) m z+foldlWithKey f z (TMap m) = foldlM (\ z (Assoc k a) -> f z k a) m z -- | Map each key\/element pair to an action, evaluate these actions from left to right, and collect the results.+{-# INLINE traverseWithKey #-} traverseWithKey :: (TKey k, Applicative f) => (k -> a -> f b) -> TMap k a -> f (TMap k b)-traverseWithKey f (TMap m) = TMap <$> traverseWithKeyM (\ k (Elem a) -> Elem <$> f (fromRep k) a) m+traverseWithKey f (TMap m) = TMap <$> traverseM (\ (Assoc k a) -> Assoc k <$> f k a) m -- | Map a function over all values in the map. --@@ -343,7 +354,7 @@ -- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")] {-# INLINEABLE mapWithKey #-} mapWithKey :: TKey k => (k -> a -> b) -> TMap k a -> TMap k b-mapWithKey f (TMap m) = TMap (mapWithKeyM (\ k (Elem a) -> Elem (f (fromRep k) a)) m)+mapWithKey f (TMap m) = TMap (fmapM (\ (Assoc k a) -> Assoc k (f k a)) m) -- | -- @'mapKeys' f s@ is the map obtained by applying @f@ to each key of @s@.@@ -432,9 +443,10 @@ {-# INLINEABLE unionMaybeWithKey #-} unionMaybeWithKey :: TKey k => (k -> a -> a -> Maybe a) -> TMap k a -> TMap k a -> TMap k a unionMaybeWithKey f (TMap m1) (TMap m2) = TMap (unionM f' m1 m2) where- f' k (Elem a) (Elem b) = Elem <$> f (fromRep k) a b+ f' (Assoc k a) (Assoc _ b) = Assoc k <$> f k a b -- | 'symmetricDifference' is equivalent to @'unionMaybeWith' (\ _ _ -> Nothing)@.+{-# INLINE symmetricDifference #-} symmetricDifference :: TKey k => TMap k a -> TMap k a -> TMap k a symmetricDifference = unionMaybeWith (\ _ _ -> Nothing) @@ -474,13 +486,14 @@ {-# INLINEABLE intersectionMaybeWithKey #-} intersectionMaybeWithKey :: TKey k => (k -> a -> b -> Maybe c) -> TMap k a -> TMap k b -> TMap k c intersectionMaybeWithKey f (TMap m1) (TMap m2) = TMap (isectM f' m1 m2) where- f' k (Elem a) (Elem b) = Elem <$> f (fromRep k) a b+ f' (Assoc k a) (Assoc _ b) = Assoc k <$> f k a b -- | Difference of two maps. -- Return elements of the first map not existing in the second map. -- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/. -- -- > difference (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 3 "b"+{-# INLINE difference #-} difference :: TKey k => TMap k a -> TMap k b -> TMap k a difference = differenceWith (\ _ _ -> Nothing) @@ -514,7 +527,7 @@ {-# INLINEABLE differenceWithKey #-} differenceWithKey :: TKey k => (k -> a -> b -> Maybe a) -> TMap k a -> TMap k b -> TMap k a differenceWithKey f (TMap m1) (TMap m2) = TMap (diffM f' m1 m2) where- f' k (Elem a) (Elem b) = Elem <$> f (fromRep k) a b+ f' (Assoc k a) (Assoc _ b) = Assoc k <$> f k a b -- | Retrieves the value associated with minimal key of the -- map, and the map stripped of that element, or 'Nothing' if passed an@@ -584,10 +597,10 @@ updateMax = updateMaxWithKey . const {-# INLINE updateHelper #-}-updateHelper :: (TKey k, MonadPlus m) => (k -> a -> Maybe a) -> TMap k a -> m (Maybe (Elem a), Hole (Rep k) (Elem a))+updateHelper :: (TKey k, MonadPlus m) => (k -> a -> Maybe a) -> TMap k a -> m (Maybe (Assoc k a), Hole (Rep k) (Assoc k a)) updateHelper f (TMap m) = do- (Elem a, loc) <- extractHoleM m- return (Elem <$> f (fromRep (keyM loc)) a, loc)+ (Assoc k a, loc) <- extractHoleM m+ return (Assoc k <$> f k a, loc) -- | Update the value at the minimal key. --@@ -625,23 +638,23 @@ deleteFindMax :: TKey k => TMap k a -> ((k, a), TMap k a) deleteFindMax m = fromMaybe (error "Cannot return the maximal element of an empty map") (maxViewWithKey m) -{-# INLINE minViewWithKey #-} -- | Retrieves the minimal (key,value) pair of the map, and -- the map stripped of that element, or 'Nothing' if passed an empty map. -- -- > minViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((3,"b"), singleton 5 "a") -- > minViewWithKey empty == Nothing minViewWithKey :: TKey k => TMap k a -> Maybe ((k, a), TMap k a)+{-# INLINE minViewWithKey #-} minViewWithKey m = do (a, loc) <- minLocation m return ((key loc, a), after loc) -{-# INLINE maxViewWithKey #-} -- | /O(log n)/. Retrieves the maximal (key,value) pair of the map, and -- the map stripped of that element, or 'Nothing' if passed an empty map. -- -- > maxViewWithKey (fromList [(5,"a"), (3,"b")]) == Just ((5,"a"), singleton 3 "b") -- > maxViewWithKey empty == Nothing+{-# INLINE maxViewWithKey #-} maxViewWithKey :: TKey k => TMap k a -> Maybe ((k, a), TMap k a) maxViewWithKey m = do (a, loc) <- maxLocation m@@ -696,9 +709,9 @@ mapEitherWithKey :: TKey k => (k -> a -> Either b c) -> TMap k a -> (TMap k b, TMap k c) mapEitherWithKey f (TMap m) = case mapEitherM f' m of (# mL, mR #) -> (TMap mL, TMap mR) - where f' k (Elem a) = case f (fromRep k) a of- Left b -> (# Just (Elem b), Nothing #)- Right c -> (# Nothing, Just (Elem c) #)+ where f' (Assoc k a) = case f k a of+ Left b -> (# Just (Assoc k b), Nothing #)+ Right c -> (# Nothing, Just (Assoc k c) #) -- | /O(n)/. Map values and collect the 'Just' results. --@@ -714,7 +727,7 @@ -- > mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) == singleton 3 "key : 3" {-# INLINEABLE mapMaybeWithKey #-} mapMaybeWithKey :: TKey k => (k -> a -> Maybe b) -> TMap k a -> TMap k b-mapMaybeWithKey f (TMap m) = TMap (mapMaybeM (\ k (Elem a) -> Elem <$> f (fromRep k) a) m)+mapMaybeWithKey f (TMap m) = TMap (mapMaybeM (\ (Assoc k a) -> Assoc k <$> f k a) m) -- | Partition the map according to a predicate. The first -- map contains all elements that satisfy the predicate, the second all@@ -763,6 +776,7 @@ -- > split 4 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", singleton 5 "a") -- > split 5 (fromList [(5,"a"), (3,"b")]) == (singleton 3 "b", empty) -- > split 6 (fromList [(5,"a"), (3,"b")]) == (fromList [(3,"b"), (5,"a")], empty)+{-# INLINE split #-} split :: TKey k => k -> TMap k a -> (TMap k a, TMap k a) split k m = case splitLookup k m of (mL, _, mR) -> (mL, mR)@@ -806,7 +820,7 @@ {-# INLINEABLE isSubmapOfBy #-} isSubmapOfBy :: TKey k => (a -> b -> Bool) -> TMap k a -> TMap k b -> Bool isSubmapOfBy (<=) (TMap m1) (TMap m2) = isSubmapM (<<=) m1 m2 where- Elem a <<= Elem b = a <= b+ Assoc _ a <<= Assoc _ b = a <= b -- | Build a map from a list of key\/value pairs. See also 'fromAscList'. -- If the list contains more than one value for the same key, the last value@@ -850,8 +864,8 @@ -- > fromListWith (++) [] == empty {-# INLINEABLE fromListWithKey #-} fromListWithKey :: TKey k => (k -> a -> a -> a) -> [(k, a)] -> TMap k a-fromListWithKey f xs = TMap (fromListM f' [(toRep k, Elem a) | (k, a) <- xs])- where f' k (Elem a) (Elem b) = Elem (f (fromRep k) a b)+fromListWithKey f xs = TMap (fromListM f' [(toRep k, Assoc k a) | (k, a) <- xs])+ where f' (Assoc k a) (Assoc _ b) = Assoc k (f k a b) -- | Build a map from an ascending list in linear time. -- /The precondition (input list is ascending) is not checked./@@ -860,8 +874,8 @@ -- > fromAscList [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "b")] {-# INLINEABLE fromAscListWithKey #-} fromAscListWithKey :: TKey k => (k -> a -> a -> a) -> [(k, a)] -> TMap k a-fromAscListWithKey f xs = TMap (fromAscListM f' [(toRep k, Elem a) | (k, a) <- xs])- where f' k (Elem a) (Elem b) = Elem (f (fromRep k) a b)+fromAscListWithKey f xs = TMap (fromAscListM f' [(toRep k, Assoc k a) | (k, a) <- xs])+ where f' (Assoc k a) (Assoc _ b) = Assoc k (f k a b) -- | Build a map from an ascending list of distinct elements in linear time. -- /The precondition is not checked./@@ -869,13 +883,14 @@ -- > fromDistinctAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")] {-# INLINEABLE fromDistinctAscList #-} fromDistinctAscList :: TKey k => [(k, a)] -> TMap k a-fromDistinctAscList xs = TMap (fromDistAscListM [(toRep k, Elem a) | (k, a) <- xs])+fromDistinctAscList xs = TMap (fromDistAscListM [(toRep k, Assoc k a) | (k, a) <- xs]) -- | /O(1)/. The number of elements in the map. -- -- > size empty == 0 -- > size (singleton 1 'a') == 1 -- > size (fromList([(1,'a'), (2,'c'), (3,'b')])) == 3+{-# INLINE size #-} size :: TKey k => TMap k a -> Int size (TMap m) = getSize m @@ -904,16 +919,19 @@ keysSet m = TSet (() <$ m) -- | /O(1)/. The key marking the position of the \"hole\" in the map.+{-# INLINE key #-} key :: TKey k => TLocation k a -> k-key (TLoc hole) = fromRep (keyM hole)+key (TLoc k _) = k -- | @'before' loc@ is the submap with keys less than @'key' loc@.+{-# INLINE before #-} before :: TKey k => TLocation k a -> TMap k a-before (TLoc hole) = TMap (beforeM Nothing hole)+before (TLoc _ hole) = TMap (beforeM Nothing hole) -- | @'after' loc@ is the submap with keys greater than @'key' loc@.+{-# INLINE after #-} after :: TKey k => TLocation k a -> TMap k a-after (TLoc hole) = TMap (afterM Nothing hole)+after (TLoc _ hole) = TMap (afterM Nothing hole) -- | Search the map for the given key, returning the -- corresponding value (if any) and an updatable location for that key.@@ -927,9 +945,11 @@ -- @ -- -- @'lookup' k m == 'fst' ('search' k m)@+{-# INLINE search #-} search :: TKey k => k -> TMap k a -> (Maybe a, TLocation k a) search k (TMap m) = case searchM (toRep k) m of- (# a, hole #) -> (getElem <$> a, TLoc hole)+ (# Just (Assoc k a), hole #) -> (Just a, TLoc k hole)+ (# _, hole #) -> (Nothing, TLoc k hole) -- | Return the value and an updatable location for the -- /i/th key in the map. Calls 'error' if /i/ is out of range.@@ -949,13 +969,13 @@ | i < 0 || i >= size m = error "TrieMap.index: index out of range" index i (TMap m) = case indexM (unbox i) m of- (# _, Elem a, hole #) -> (a, TLoc hole)+ (# _, Assoc k a, hole #) -> (a, TLoc k hole) {-# INLINE extract #-} extract :: (TKey k, MonadPlus m) => TMap k a -> m (a, TLocation k a) extract (TMap m) = do- (Elem a, hole) <- extractHoleM m- return (a, TLoc hole)+ (Assoc k a, hole) <- extractHoleM m+ return (a, TLoc k hole) -- | /O(log n)/. Return the value and an updatable location for the -- least key in the map, or 'Nothing' if the map is empty.@@ -993,14 +1013,16 @@ -- at the location (replacing an existing value, if any). -- -- @'assign' v loc == 'before' loc `union` 'singleton' ('key' loc) v `union` 'after' loc@+{-# INLINE assign #-} assign :: TKey k => a -> TLocation k a -> TMap k a-assign a (TLoc hole) = TMap (assignM (Elem a) hole)+assign a (TLoc k hole) = TMap (assignM (Just $ Assoc k a) hole) -- | Return a map obtained by erasing the location. -- -- @'clear' loc == 'before' loc `union` 'after' loc@+{-# INLINE clear #-} clear :: TKey k => TLocation k a -> TMap k a-clear (TLoc hole) = TMap (clearM hole)+clear (TLoc _ hole) = TMap (assignM Nothing hole) {-# INLINE fillHole #-} fillHole :: TKey k => Maybe a -> TLocation k a -> TMap k a
Data/TrieMap/Class.hs view
@@ -1,21 +1,24 @@ {-# LANGUAGE TypeFamilies, FlexibleContexts, FlexibleInstances, UndecidableInstances #-} -module Data.TrieMap.Class (TMap(..), TSet (..), TKey, Rep, TrieMap, TrieKey) where+module Data.TrieMap.Class (TMap(..), TSet(..), TKey, Rep, TrieMap, TrieKey) where import Data.TrieMap.TrieKey-import Data.TrieMap.Rep+import Data.TrieMap.Representation.Class import Data.TrieMap.Sized import Control.Applicative-import Data.Foldable+import Data.Foldable hiding (foldrM, foldlM) import Data.Traversable import Prelude hiding (foldr) -newtype TMap k a = TMap {getTMap :: TrieMap (Rep k) (Elem a)}+newtype TMap k a = TMap {getTMap :: TrieMap (Rep k) (Assoc k a)} newtype TSet a = TSet (TMap a ()) +-- | @'TKey' k@ is a handy alias for @('Repr' k, 'TrieKey' ('Rep' k))@. To make a type an instance of 'TKey',+-- use the methods available in "Data.TrieMap.Representation.TH" to generate a 'Repr' instance that will+-- satisfy @'TrieKey' ('Rep' k)@. class (Repr k, TrieKey (Rep k)) => TKey k instance (Repr k, TrieKey (Rep k)) => TKey k@@ -24,7 +27,7 @@ fmap = fmapDefault instance TKey k => Foldable (TMap k) where- foldr f z (TMap m) = foldrWithKeyM (\ _ (Elem a) -> f a) m z+ foldr f z (TMap m) = foldrM (\ (Assoc _ a) -> f a) m z instance TKey k => Traversable (TMap k) where- traverse f (TMap m) = TMap <$> traverseWithKeyM (\ _ (Elem a) -> Elem <$> f a) m+ traverse f (TMap m) = TMap <$> traverseM (\ (Assoc k a) -> Assoc k <$> f a) m
Data/TrieMap/Class/Instances.hs view
@@ -2,14 +2,12 @@ import Data.TrieMap.Class () import Data.TrieMap.TrieKey ()-import Data.TrieMap.Rep ()-import Data.TrieMap.Rep.Instances ()-import Data.TrieMap.Representation ()+import Data.TrieMap.Representation.Instances () import Data.TrieMap.Sized ()+import Data.TrieMap.ReverseMap () import Data.TrieMap.RadixTrie () import Data.TrieMap.IntMap () import Data.TrieMap.OrdMap ()-import Data.TrieMap.ReverseMap () import Data.TrieMap.ProdMap () import Data.TrieMap.UnionMap () import Data.TrieMap.UnitMap()
Data/TrieMap/IntMap.hs view
@@ -12,62 +12,49 @@ import Data.Maybe hiding (mapMaybe) import Data.Word +import GHC.Exts+ import Prelude hiding (lookup, null, foldl, foldr) #include "MachDeps.h"-#if WORD_SIZE_IN_BITS == 32-import GHC.Prim-import GHC.Word--complement32 (W32# w#) = W32# (not# w#)-#elif WORD_SIZE_IN_BITS > 32-complement32 = xor (bit 32 - 1)-#else-import GHC.Prim-import GHC.IntWord32-complement32 (W32# w#) = W32# (not32# w#)-#endif-complement32 :: Word32 -> Word32--{-# RULES- "complement/Word32" complement = complement32- #-}--type Nat = Word32+type Nat = Word -type Prefix = Word32-type Mask = Word32-type Key = Word32+type Prefix = Word+type Mask = Word+type Key = Word type Size = Int# data Path a = Root - | LeftBin !Prefix !Mask !(Path a) !(TrieMap Word32 a)- | RightBin !Prefix !Mask !(TrieMap Word32 a) !(Path a)+ | LeftBin !Prefix !Mask !(Path a) !(TrieMap Word a)+ | RightBin !Prefix !Mask !(TrieMap Word a) !(Path a) -instance TrieKey Word32 where- data TrieMap Word32 a = Nil+instance TrieKey Word where+ (=?) = (==)+ cmp = compare++ data TrieMap Word a = Nil | Tip !Size !Key a- | Bin !Size !Prefix !Mask !(TrieMap Word32 a) !(TrieMap Word32 a)- data Hole Word32 a = Hole !Key !(Path a)+ | Bin !Size !Prefix !Mask !(TrieMap Word a) !(TrieMap Word a)+ data Hole Word a = Hole !Key !(Path a) emptyM = Nil singletonM = singleton- nullM = null+ getSimpleM Nil = Null+ getSimpleM (Tip _ _ a) = Singleton a+ getSimpleM _ = NonSimple sizeM = size lookupM = lookup- traverseWithKeyM = traverseWithKey- foldrWithKeyM = foldr- foldlWithKeyM = foldl- mapWithKeyM = mapWithKey+ traverseM = traverse+ foldrM = foldr+ foldlM = foldl+ fmapM = mapWithKey mapMaybeM = mapMaybe mapEitherM = mapEither- unionM = unionWithKey- isectM = intersectionWithKey- diffM = differenceWithKey--- extractM f = extract f+ unionM = unionWith+ isectM = intersectionWith+ diffM = differenceWith isSubmapM = isSubmapOfBy singleHoleM k = Hole k Root- keyM (Hole k _) = k beforeM a (Hole k path) = before (singletonMaybe k a) path where before t Root = t before t (LeftBin _ _ path _) = before t path@@ -76,7 +63,7 @@ after t Root = t after t (RightBin _ _ _ path) = after t path after t (LeftBin p m path r) = after (bin p m t r) path- searchM !k = onUnboxed (Hole k) (search Root) where+ searchM !k = onSnd (Hole k) (search Root) where search path t@(Bin _ p m l r) | nomatch k p m = (# Nothing, branchHole k p path t #) | zero k m@@ -88,8 +75,7 @@ | otherwise = (# Nothing, branchHole k ky path t #) search path _ = (# Nothing, path #) indexM i# t = indexT i# t Root where- indexT _ Nil _ = (# error err, error err, error err #) where- err = "Error: empty trie"+ indexT _ Nil _ = indexFail () indexT i# (Tip _ kx x) path = (# i#, x, Hole kx path #) indexT i# (Bin _ p m l r) path | i# <# sl# = indexT i# l (LeftBin p m path r)@@ -101,27 +87,25 @@ extractHole path (Bin _ p m l r) = extractHole (LeftBin p m path r) l `mplus` extractHole (RightBin p m l path) r- assignM v (Hole kx path) = assign (singleton kx v) path where+ assignM v (Hole kx path) = assign (singletonM' kx v) path where assign t Root = t assign t (LeftBin p m path r) = assign (bin p m t r) path assign t (RightBin p m l path) = assign (bin p m l t) path - clearM (Hole _ path) = clear Nil path where- clear t Root = t- clear t (LeftBin p m path r) = clear (bin p m t r) path- clear t (RightBin p m l path) = clear (bin p m l t) path+ {-# INLINE unifyM #-}+ unifyM = unify -branchHole :: Key -> Prefix -> Path a -> TrieMap Word32 a -> Path a+branchHole :: Key -> Prefix -> Path a -> TrieMap Word a -> Path a branchHole !k !p path t | zero k m = LeftBin p' m path t | otherwise = RightBin p' m t path where m = branchMask k p p' = mask k m -natFromInt :: Word32 -> Nat+natFromInt :: Word -> Nat natFromInt = id -intFromNat :: Nat -> Word32+intFromNat :: Nat -> Word intFromNat = id shiftRL :: Nat -> Key -> Nat@@ -135,127 +119,121 @@ shiftRL x i = shiftR x (fromIntegral i) -- #endif -size :: TrieMap Word32 a -> Int#+size :: TrieMap Word a -> Int# size Nil = 0# size (Tip sz _ _) = sz size (Bin sz _ _ _ _) = sz -null :: TrieMap Word32 a -> Bool-null Nil = True-null _ = False--lookup :: Nat -> TrieMap Word32 a -> Maybe a-lookup k (Bin _ _ m l r) = lookup k (if zeroN k m then l else r)+lookup :: Nat -> TrieMap Word a -> Maybe a+lookup !k (Bin _ _ m l r) = lookup k (if zeroN k m then l else r) lookup k (Tip _ kx x) | k == kx = Just x lookup _ _ = Nothing -singleton :: Sized a => Key -> a -> TrieMap Word32 a+singleton :: Sized a => Key -> a -> TrieMap Word a singleton k a = Tip (getSize# a) k a -singletonMaybe :: Sized a => Key -> Maybe a -> TrieMap Word32 a+singletonMaybe :: Sized a => Key -> Maybe a -> TrieMap Word a singletonMaybe k = maybe Nil (singleton k) -traverseWithKey :: (Applicative f, Sized b) => (Key -> a -> f b) -> TrieMap Word32 a -> f (TrieMap Word32 b)-traverseWithKey f t = case t of+traverse :: (Applicative f, Sized b) => (a -> f b) -> TrieMap Word a -> f (TrieMap Word b)+traverse f t = case t of Nil -> pure Nil- Tip _ kx x -> singleton kx <$> f kx x- Bin _ p m l r -> bin p m <$> traverseWithKey f l <*> traverseWithKey f r+ Tip _ kx x -> singleton kx <$> f x+ Bin _ p m l r -> bin p m <$> traverse f l <*> traverse f r -foldr :: (Key -> a -> b -> b) -> TrieMap Word32 a -> b -> b+foldr :: (a -> b -> b) -> TrieMap Word a -> b -> b foldr f t = case t of Bin _ _ _ l r -> foldr f l . foldr f r- Tip _ k x -> f k x+ Tip _ _ x -> f x Nil -> id -foldl :: (Key -> b -> a -> b) -> TrieMap Word32 a -> b -> b+foldl :: (b -> a -> b) -> TrieMap Word a -> b -> b foldl f t = case t of Bin _ _ _ l r -> foldl f r . foldl f l- Tip _ k x -> flip (f k) x+ Tip _ _ x -> flip f x Nil -> id -mapWithKey :: Sized b => (Key -> a -> b) -> TrieMap Word32 a -> TrieMap Word32 b+mapWithKey :: Sized b => (a -> b) -> TrieMap Word a -> TrieMap Word b mapWithKey f (Bin _ p m l r) = bin p m (mapWithKey f l) (mapWithKey f r)-mapWithKey f (Tip _ kx x) = singleton kx (f kx x)+mapWithKey f (Tip _ kx x) = singleton kx (f x) mapWithKey _ _ = Nil -mapMaybe :: Sized b => (Key -> a -> Maybe b) -> TrieMap Word32 a -> TrieMap Word32 b+mapMaybe :: Sized b => (a -> Maybe b) -> TrieMap Word a -> TrieMap Word b mapMaybe f (Bin _ p m l r) = bin p m (mapMaybe f l) (mapMaybe f r)-mapMaybe f (Tip _ kx x) = singletonMaybe kx (f kx x)+mapMaybe f (Tip _ kx x) = singletonMaybe kx (f x) mapMaybe _ _ = Nil -mapEither :: (Sized b, Sized c) => EitherMap Key a b c ->- TrieMap Word32 a -> (# TrieMap Word32 b, TrieMap Word32 c #)-mapEither f (Bin _ p m l r) - | (# lL, lR #) <- mapEither f l, - (# rL, rR #) <- mapEither f r- = (# bin p m lL rL, bin p m lR rR #)-mapEither f (Tip _ kx x) = both (singletonMaybe kx) (singletonMaybe kx) (f kx) x+mapEither :: (Sized b, Sized c) => (a -> (# Maybe b, Maybe c #)) -> + TrieMap Word a -> (# TrieMap Word b, TrieMap Word c #)+mapEither f (Bin _ p m l r) = both (bin p m lL) (bin p m lR) (mapEither f) r+ where !(# lL, lR #) = mapEither f l+mapEither f (Tip _ kx x) = both (singletonMaybe kx) (singletonMaybe kx) f x mapEither _ _ = (# Nil, Nil #) -unionWithKey :: Sized a => UnionFunc Key a -> TrieMap Word32 a -> TrieMap Word32 a -> TrieMap Word32 a-unionWithKey _ Nil t = t-unionWithKey _ t Nil = t-unionWithKey f (Tip _ k x) t = alterM (maybe (Just x) (f k x)) k t-unionWithKey f t (Tip _ k x) = alterM (maybe (Just x) (flip (f k) x)) k t-unionWithKey f t1@(Bin _ p1 m1 l1 r1) t2@(Bin _ p2 m2 l2 r2)+unionWith :: Sized a => (a -> a -> Maybe a) -> TrieMap Word a -> TrieMap Word a -> TrieMap Word a+unionWith _ Nil t = t+unionWith _ t Nil = t+unionWith f (Tip _ k x) t = alterM (maybe (Just x) (f x)) k t+unionWith f t (Tip _ k x) = alterM (maybe (Just x) (flip f x)) k t+unionWith f t1@(Bin _ p1 m1 l1 r1) t2@(Bin _ p2 m2 l2 r2) | shorter m1 m2 = union1 | shorter m2 m1 = union2- | p1 == p2 = bin p1 m1 (unionWithKey f l1 l2) (unionWithKey f r1 r2)+ | p1 == p2 = bin p1 m1 (unionWith f l1 l2) (unionWith f r1 r2) | otherwise = join p1 t1 p2 t2 where union1 | nomatch p2 p1 m1 = join p1 t1 p2 t2- | zero p2 m1 = bin p1 m1 (unionWithKey f l1 t2) r1- | otherwise = bin p1 m1 l1 (unionWithKey f r1 t2)+ | zero p2 m1 = bin p1 m1 (unionWith f l1 t2) r1+ | otherwise = bin p1 m1 l1 (unionWith f r1 t2) union2 | nomatch p1 p2 m2 = join p1 t1 p2 t2- | zero p1 m2 = bin p2 m2 (unionWithKey f t1 l2) r2- | otherwise = bin p2 m2 l2 (unionWithKey f t1 r2)+ | zero p1 m2 = bin p2 m2 (unionWith f t1 l2) r2+ | otherwise = bin p2 m2 l2 (unionWith f t1 r2) -intersectionWithKey :: Sized c => IsectFunc Key a b c -> TrieMap Word32 a -> TrieMap Word32 b -> TrieMap Word32 c-intersectionWithKey _ Nil _ = Nil-intersectionWithKey _ _ Nil = Nil-intersectionWithKey f (Tip _ k x) t2- = singletonMaybe k (lookup (natFromInt k) t2 >>= f k x)-intersectionWithKey f t1 (Tip _ k y) - = singletonMaybe k (lookup (natFromInt k) t1 >>= flip (f k) y)-intersectionWithKey f t1@(Bin _ p1 m1 l1 r1) t2@(Bin _ p2 m2 l2 r2)+intersectionWith :: Sized c => (a -> b -> Maybe c) -> TrieMap Word a -> TrieMap Word b -> TrieMap Word c+intersectionWith _ Nil _ = Nil+intersectionWith _ _ Nil = Nil+intersectionWith f (Tip _ k x) t2+ = singletonMaybe k (lookup (natFromInt k) t2 >>= f x)+intersectionWith f t1 (Tip _ k y) + = singletonMaybe k (lookup (natFromInt k) t1 >>= flip f y)+intersectionWith f t1@(Bin _ p1 m1 l1 r1) t2@(Bin _ p2 m2 l2 r2) | shorter m1 m2 = intersection1 | shorter m2 m1 = intersection2- | p1 == p2 = bin p1 m1 (intersectionWithKey f l1 l2) (intersectionWithKey f r1 r2)+ | p1 == p2 = bin p1 m1 (intersectionWith f l1 l2) (intersectionWith f r1 r2) | otherwise = Nil where intersection1 | nomatch p2 p1 m1 = Nil- | zero p2 m1 = intersectionWithKey f l1 t2- | otherwise = intersectionWithKey f r1 t2+ | zero p2 m1 = intersectionWith f l1 t2+ | otherwise = intersectionWith f r1 t2 intersection2 | nomatch p1 p2 m2 = Nil- | zero p1 m2 = intersectionWithKey f t1 l2- | otherwise = intersectionWithKey f t1 r2+ | zero p1 m2 = intersectionWith f t1 l2+ | otherwise = intersectionWith f t1 r2 -differenceWithKey :: Sized a => (Key -> a -> b -> Maybe a) -> TrieMap Word32 a -> TrieMap Word32 b -> TrieMap Word32 a-differenceWithKey _ Nil _ = Nil-differenceWithKey _ t Nil = t-differenceWithKey f t1@(Tip _ k x) t2 - = maybe t1 (singletonMaybe k . f k x) (lookup (natFromInt k) t2)-differenceWithKey f t (Tip _ k y) = alterM (>>= flip (f k) y) k t-differenceWithKey f t1@(Bin _ p1 m1 l1 r1) t2@(Bin _ p2 m2 l2 r2)+differenceWith :: Sized a => (a -> b -> Maybe a) -> TrieMap Word a -> TrieMap Word b -> TrieMap Word a+differenceWith _ Nil _ = Nil+differenceWith _ t Nil = t+differenceWith f t1@(Tip _ k x) t2 + = maybe t1 (singletonMaybe k . f x) (lookup (natFromInt k) t2)+differenceWith f t (Tip _ k y) = alterM (>>= flip f y) k t+differenceWith f t1@(Bin _ p1 m1 l1 r1) t2@(Bin _ p2 m2 l2 r2) | shorter m1 m2 = difference1 | shorter m2 m1 = difference2- | p1 == p2 = bin p1 m1 (differenceWithKey f l1 l2) (differenceWithKey f r1 r2)+ | p1 == p2 = bin p1 m1 (differenceWith f l1 l2) (differenceWith f r1 r2) | otherwise = t1 where difference1 | nomatch p2 p1 m1 = t1- | zero p2 m1 = bin p1 m1 (differenceWithKey f l1 t2) r1- | otherwise = bin p1 m1 l1 (differenceWithKey f r1 t2)+ | zero p2 m1 = bin p1 m1 (differenceWith f l1 t2) r1+ | otherwise = bin p1 m1 l1 (differenceWith f r1 t2) difference2 | nomatch p1 p2 m2 = t1- | zero p1 m2 = differenceWithKey f t1 l2- | otherwise = differenceWithKey f t1 r2+ | zero p1 m2 = differenceWith f t1 l2+ | otherwise = differenceWith f t1 r2 -isSubmapOfBy :: LEq a b -> LEq (TrieMap Word32 a) (TrieMap Word32 b)+isSubmapOfBy :: LEq a b -> LEq (TrieMap Word a) (TrieMap Word b) isSubmapOfBy (<=) t1@(Bin _ p1 m1 l1 r1) (Bin _ p2 m2 l2 r2) | shorter m1 m2 = False | shorter m2 m1 = match p1 p2 m2 && (if zero p1 m2 then isSubmapOfBy (<=) t1 l2@@ -268,12 +246,6 @@ isSubmapOfBy _ Nil _ = True --- extract :: Alternative f => Sized a -> (Key -> a -> f (x, Maybe a)) -> TrieMap Word32 a -> f (x, TrieMap Word32 a)--- extract f (Bin _ p m l r) = --- fmap (\ l' -> bin p m l' r) <$> extract f l <|> fmap (bin p m l) <$> extract f r--- extract f (Tip _ k x) = fmap (singletonMaybe k) <$> f k x--- extract _ _ _ = empty- mask :: Key -> Mask -> Prefix mask i m = maskW (natFromInt i) (natFromInt m)@@ -318,7 +290,8 @@ x5 -> x5 `xor` shiftRL x5 1 #endif -join :: Prefix -> TrieMap Word32 a -> Prefix -> TrieMap Word32 a -> TrieMap Word32 a+{-# INLINE join #-}+join :: Prefix -> TrieMap Word a -> Prefix -> TrieMap Word a -> TrieMap Word a join p1 t1 p2 t2 | zero p1 m = bin p m t1 t2 | otherwise = bin p m t2 t1@@ -326,7 +299,19 @@ m = branchMask p1 p2 p = mask p1 m -bin :: Prefix -> Mask -> TrieMap Word32 a -> TrieMap Word32 a -> TrieMap Word32 a+bin :: Prefix -> Mask -> TrieMap Word a -> TrieMap Word a -> TrieMap Word a bin _ _ l Nil = l bin _ _ Nil r = r bin p m l r = Bin (size l +# size r) p m l r++{-# INLINE unify #-}+unify :: Sized a => Key -> a -> Key -> a -> Unified Word a+unify k1 _ k2 _+ | k1 == k2 = Left (Hole k1 Root)+unify k1 a1 k2 a2 = Right (if zero k1 m then outBin t1 t2 else outBin t2 t1)+ where !s1# = getSize# a1+ !s2# = getSize# a2+ t1 = Tip s1# k1 a1+ t2 = Tip s2# k2 a2+ m = branchMask k1 k2+ outBin = Bin (s1# +# s2#) (mask k1 m) m
Data/TrieMap/Key.hs view
@@ -1,42 +1,52 @@ {-# LANGUAGE TypeFamilies, UnboxedTuples #-} -module Data.TrieMap.Key (Key(..)) where+module Data.TrieMap.Key () where import Control.Applicative+ import Data.TrieMap.Class import Data.TrieMap.TrieKey-import Data.TrieMap.Rep+import Data.TrieMap.Representation.Class import Data.TrieMap.Modifiers +import Data.TrieMap.ProdMap()+import Data.TrieMap.UnionMap()+import Data.TrieMap.IntMap()+import Data.TrieMap.OrdMap()+import Data.TrieMap.RadixTrie()+ instance TKey k => TrieKey (Key k) where+ Key k1 =? Key k2 = toRep k1 =? toRep k2+ Key k1 `cmp` Key k2 = toRep k1 `cmp` toRep k2+ newtype TrieMap (Key k) a = KeyMap (TrieMap (Rep k) a) newtype Hole (Key k) a = KeyHole (Hole (Rep k) a) emptyM = KeyMap emptyM singletonM (Key k) a = KeyMap (singletonM (toRep k) a)- nullM (KeyMap m) = nullM m+ getSimpleM (KeyMap m) = getSimpleM m sizeM (KeyMap m) = sizeM m lookupM (Key k) (KeyMap m) = lookupM (toRep k) m- traverseWithKeyM f (KeyMap m) = KeyMap <$> traverseWithKeyM (f . Key . fromRep) m- foldrWithKeyM f (KeyMap m) = foldrWithKeyM (f . Key . fromRep) m- foldlWithKeyM f (KeyMap m) = foldlWithKeyM (f . Key . fromRep) m- mapWithKeyM f (KeyMap m) = KeyMap (mapWithKeyM (f . Key . fromRep) m)- mapMaybeM f (KeyMap m) = KeyMap (mapMaybeM (f . Key . fromRep) m)- mapEitherM f (KeyMap m) = both KeyMap KeyMap (mapEitherM (f . Key . fromRep)) m- unionM f (KeyMap m1) (KeyMap m2) = KeyMap (unionM (f . Key . fromRep) m1 m2)- isectM f (KeyMap m1) (KeyMap m2) = KeyMap (isectM (f . Key . fromRep) m1 m2)- diffM f (KeyMap m1) (KeyMap m2) = KeyMap (diffM (f . Key . fromRep) m1 m2)+ traverseM f (KeyMap m) = KeyMap <$> traverseM f m+ foldrM f (KeyMap m) = foldrM f m+ foldlM f (KeyMap m) = foldlM f m+ fmapM f (KeyMap m) = KeyMap (fmapM f m)+ mapMaybeM f (KeyMap m) = KeyMap (mapMaybeM f m)+ mapEitherM f (KeyMap m) = both KeyMap KeyMap (mapEitherM f) m+ unionM f (KeyMap m1) (KeyMap m2) = KeyMap (unionM f m1 m2)+ isectM f (KeyMap m1) (KeyMap m2) = KeyMap (isectM f m1 m2)+ diffM f (KeyMap m1) (KeyMap m2) = KeyMap (diffM f m1 m2) isSubmapM (<=) (KeyMap m1) (KeyMap m2) = isSubmapM (<=) m1 m2 singleHoleM (Key k) = KeyHole (singleHoleM (toRep k))- keyM (KeyHole hole) = Key (fromRep (keyM hole)) beforeM a (KeyHole hole) = KeyMap (beforeM a hole) afterM a (KeyHole hole) = KeyMap (afterM a hole)- searchM (Key k) (KeyMap m) = onUnboxed KeyHole (searchM (toRep k)) m+ searchM (Key k) (KeyMap m) = onSnd KeyHole (searchM (toRep k)) m indexM i (KeyMap m) = case indexM i m of (# i', v, hole #) -> (# i', v, KeyHole hole #) extractHoleM (KeyMap m) = do (v, hole) <- extractHoleM m return (v, KeyHole hole) assignM v (KeyHole hole) = KeyMap (assignM v hole)- clearM (KeyHole hole) = KeyMap (clearM hole)+ + unifyM (Key k1) a1 (Key k2) a2 = either (Left . KeyHole) (Right . KeyMap) (unifyM (toRep k1) a1 (toRep k2) a2)
Data/TrieMap/Modifiers.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE FlexibleContexts, UndecidableInstances, TypeFamilies #-} module Data.TrieMap.Modifiers where -import Data.TrieMap.Rep+import Data.TrieMap.Representation.Class newtype Ordered a = Ord {unOrd :: a} deriving (Eq, Ord) newtype Rev k = Rev {getRev :: k} deriving (Eq)@@ -16,17 +16,6 @@ newtype Key k = Key {getKey :: k} -instance (Repr k, Eq (Rep k)) => Eq (Key k) where- Key k1 == Key k2 = toRep k1 == toRep k2--instance (Repr k, Ord (Rep k)) => Ord (Key k) where- Key k1 `compare` Key k2 = toRep k1 `compare` toRep k2- Key k1 <= Key k2 = toRep k1 <= toRep k2- Key k1 < Key k2 = toRep k1 < toRep k2- Key k1 >= Key k2 = toRep k1 >= toRep k2- Key k1 > Key k2 = toRep k1 > toRep k2- instance Repr k => Repr (Key k) where type Rep (Key k) = Rep k toRep (Key k) = toRep k- fromRep = Key . fromRep
Data/TrieMap/OrdMap.hs view
@@ -7,9 +7,9 @@ import Data.TrieMap.Modifiers import Control.Applicative-import Control.Monad hiding (join)+import Control.Monad hiding (join, fmap) -import Prelude hiding (lookup)+import Prelude hiding (lookup, foldr, foldl, fmap) import GHC.Exts @@ -27,6 +27,9 @@ singletonMaybe k = maybe Tip (singleton k) instance Ord k => TrieKey (Ordered k) where+ Ord k1 =? Ord k2 = k1 == k2+ Ord k1 `cmp` Ord k2 = k1 `compare` k2+ data TrieMap (Ordered k) a = Tip | Bin Int# k a !(OrdMap k a) !(OrdMap k a) data Hole (Ordered k) a = @@ -34,30 +37,29 @@ | Full k !(Path k a) !(OrdMap k a) !(OrdMap k a) emptyM = Tip singletonM (Ord k) = singleton k- nullM Tip = True- nullM _ = False- sizeM = size# lookupM (Ord k) = lookup k- traverseWithKeyM f = traverseWithKey (f . Ord)- foldrWithKeyM f = foldrWithKey (f . Ord)- foldlWithKeyM f = foldlWithKey (f . Ord)- mapWithKeyM f = mapWithKey (f . Ord)- mapMaybeM f = mapMaybe (f . Ord)- mapEitherM f = mapEither (f . Ord)+ getSimpleM Tip = Null+ getSimpleM (Bin _ _ a Tip Tip) = Singleton a+ getSimpleM _ = NonSimple+ sizeM = size#+ traverseM = traverse+ foldrM = foldr+ foldlM = foldl+ fmapM = fmap+ mapMaybeM = mapMaybe+ mapEitherM = mapEither isSubmapM = isSubmap- fromAscListM f xs = fromAscList (f . Ord) [(k, a) | (Ord k, a) <- xs]+ fromAscListM f xs = fromAscList f [(k, a) | (Ord k, a) <- xs] fromDistAscListM xs = fromDistinctAscList [(k, a) | (Ord k, a) <- xs] unionM _ Tip m2 = m2 unionM _ m1 Tip = m1- unionM f m1 m2 = hedgeUnionWithKey (f . Ord) (const LT) (const GT) m1 m2- isectM f = isect (f . Ord)+ unionM f m1 m2 = hedgeUnion f (const LT) (const GT) m1 m2+ isectM = isect diffM _ Tip _ = Tip diffM _ m1 Tip = m1- diffM f m1 m2 = hedgeDiffWithKey (f . Ord) (const LT) (const GT) m1 m2+ diffM f m1 m2 = hedgeDiff f (const LT) (const GT) m1 m2 singleHoleM (Ord k) = Empty k Root- keyM (Empty k _) = Ord k- keyM (Full k _ _ _) = Ord k beforeM a (Empty k path) = before (singletonMaybe k a) path beforeM a (Full k path l _) = before t path where t = case a of@@ -76,18 +78,20 @@ | otherwise = indexT (RightBin kx x l path) (i# -# sx#) r where !sl# = size# l !sx# = getSize# x +# sl#- indexT _ _ _ = (# error err, error err, error err #) where- err = "Error: empty trie"+ indexT _ _ _ = indexFail () extractHoleM = extractHole Root where extractHole path (Bin _ kx x l r) = extractHole (LeftBin kx x path r) l `mplus` return (x, Full kx path l r) `mplus` extractHole (RightBin kx x l path) r extractHole _ _ = mzero- assignM x (Empty k path) = rebuild (singleton k x) path- assignM x (Full k path l r) = rebuild (join k x l r) path- clearM (Empty _ path) = rebuild Tip path- clearM (Full _ path l r) = rebuild (merge l r) path+ assignM x (Empty k path) = rebuild (maybe Tip (singleton k) x) path+ assignM x (Full k path l r) = rebuild (joinMaybe k x l r) path+ + unifyM (Ord k1) a1 (Ord k2) a2 = case compare k1 k2 of+ EQ -> Left $ Empty k1 Root+ LT -> Right $ bin k1 a1 Tip (singleton k2 a2)+ GT -> Right $ bin k1 a1 (singleton k2 a2) Tip rebuild :: Sized a => OrdMap k a -> Path k a -> OrdMap k a rebuild t Root = t@@ -104,63 +108,57 @@ singleton :: Sized a => k -> a -> OrdMap k a singleton k a = Bin (getSize# a) k a Tip Tip -traverseWithKey :: (Applicative f, Sized b) => (k -> a -> f b) -> OrdMap k a -> f (OrdMap k b)-traverseWithKey _ Tip = pure Tip-traverseWithKey f (Bin _ k a l r) = balance k <$> f k a <*> traverseWithKey f l <*> traverseWithKey f r+traverse :: (Applicative f, Sized b) => (a -> f b) -> OrdMap k a -> f (OrdMap k b)+traverse _ Tip = pure Tip+traverse f (Bin _ k a l r) = balance k <$> f a <*> traverse f l <*> traverse f r -foldrWithKey :: (k -> a -> b -> b) -> OrdMap k a -> b -> b-foldrWithKey _ Tip = id-foldrWithKey f (Bin _ k a l r) = foldrWithKey f l . f k a . foldrWithKey f r+foldr :: (a -> b -> b) -> OrdMap k a -> b -> b+foldr _ Tip = id+foldr f (Bin _ _ a l r) = foldr f l . f a . foldr f r -foldlWithKey :: (k -> b -> a -> b) -> OrdMap k a -> b -> b-foldlWithKey _ Tip = id-foldlWithKey f (Bin _ k a l r) = foldlWithKey f r . flip (f k) a . foldlWithKey f l+foldl :: (b -> a -> b) -> OrdMap k a -> b -> b+foldl _ Tip = id+foldl f (Bin _ _ a l r) = foldl f r . flip f a . foldl f l -mapWithKey :: (Ord k, Sized b) => (k -> a -> b) -> OrdMap k a -> OrdMap k b-mapWithKey f (Bin _ k a l r) = join k (f k a) (mapWithKey f l) (mapWithKey f r)-mapWithKey _ _ = Tip+fmap :: (Ord k, Sized b) => (a -> b) -> OrdMap k a -> OrdMap k b+fmap f (Bin _ k a l r) = join k (f a) (fmap f l) (fmap f r)+fmap _ _ = Tip -mapMaybe :: (Ord k, Sized b) => (k -> a -> Maybe b) -> OrdMap k a -> OrdMap k b-mapMaybe f (Bin _ k a l r) = joinMaybe k (f k a) (mapMaybe f l) (mapMaybe f r)+mapMaybe :: (Ord k, Sized b) => (a -> Maybe b) -> OrdMap k a -> OrdMap k b+mapMaybe f (Bin _ k a l r) = joinMaybe k (f a) (mapMaybe f l) (mapMaybe f r) mapMaybe _ _ = Tip -mapEither :: (Ord k, Sized b, Sized c) => EitherMap k a b c ->+mapEither :: (Ord k, Sized b, Sized c) => (a -> (# Maybe b, Maybe c #)) -> OrdMap k a -> (# OrdMap k b, OrdMap k c #)-mapEither f (Bin _ k a l r) - | (# aL, aR #) <- f k a,- (# lL, lR #) <- mapEither f l,- (# rL, rR #) <- mapEither f r- = (# joinMaybe k aL lL rL, joinMaybe k aR lR rR #)+mapEither f (Bin _ k a l r) = (# joinMaybe k aL lL rL, joinMaybe k aR lR rR #)+ where !(# aL, aR #) = f a; !(# lL, lR #) = mapEither f l; !(# rL, rR #) = mapEither f r mapEither _ _ = (# Tip, Tip #) splitLookup :: (Ord k, Sized a) => SplitMap a x -> k -> OrdMap k a -> (# OrdMap k a, Maybe x, OrdMap k a #) splitLookup f k m = case m of Tip -> (# Tip, Nothing, Tip #) Bin _ kx x l r -> case compare k kx of- LT -> case splitLookup f k l of- (# lL, ans, lR #) -> (# lL, ans, join kx x lR r #)- EQ -> case f x of- (# xL, ans, xR #) -> (# maybe l (\ xL -> insertMax kx xL l) xL, ans,- maybe r (\ xR -> insertMin kx xR r) xR #)- GT -> case splitLookup f k r of- (# rL, ans, rR #) -> (# join kx x l rL, ans, rR #)+ LT -> let !(# lL, ans, lR #) = splitLookup f k l in (# lL, ans, join kx x lR r #)+ EQ -> let !(# xL, ans, xR #) = f x in+ (# maybe l (\ xL -> insertMax kx xL l) xL, ans, maybe r (\ xR -> insertMin kx xR r) xR #)+ GT -> let !(# rL, ans, rR #) = splitLookup f k r in (# join kx x l rL, ans, rR #) isSubmap :: (Ord k, Sized a, Sized b) => LEq a b -> LEq (OrdMap k a) (OrdMap k b) isSubmap _ Tip _ = True isSubmap _ _ Tip = False-isSubmap (<=) (Bin _ kx x l r) t = case splitLookup (\ x -> (# Nothing, Just (Elem x), Nothing #)) kx t of- (# lt, found, gt #) -> case found of+isSubmap (<=) (Bin _ kx x l r) t = case found of Nothing -> False Just (Elem y) -> x <= y && isSubmap (<=) l lt && isSubmap (<=) r gt+ where !(# lt, found, gt #) = splitLookup (\ x -> (# Nothing, Just (Elem x), Nothing #)) kx t -fromAscList :: (Eq k, Sized a) => (k -> a -> a -> a) -> [(k, a)] -> OrdMap k a+fromAscList :: (Eq k, Sized a) => (a -> a -> a) -> [(k, a)] -> OrdMap k a fromAscList f xs = fromDistinctAscList (combineEq xs) where combineEq (x:xs) = combineEq' x xs combineEq [] = [] combineEq' z [] = [z] combineEq' (kz, zz) (x@(kx, xx):xs)- | kz == kx = combineEq' (kx, f kx xx zz) xs+ | kz == kx = combineEq' (kx, f xx zz) xs | otherwise = (kz,zz):combineEq' x xs fromDistinctAscList :: Sized a => [(k, a)] -> OrdMap k a@@ -182,24 +180,24 @@ buildR _ _ _ [] = error "fromDistinctAscList buildR []" buildB l k x c r zs = c (bin k x l r) zs -hedgeUnionWithKey :: (Ord k, Sized a)- => (k -> a -> a -> Maybe a)+hedgeUnion :: (Ord k, Sized a)+ => (a -> a -> Maybe a) -> (k -> Ordering) -> (k -> Ordering) -> OrdMap k a -> OrdMap k a -> OrdMap k a-hedgeUnionWithKey _ _ _ t1 Tip+hedgeUnion _ _ _ t1 Tip = t1-hedgeUnionWithKey _ cmplo cmphi Tip (Bin _ kx x l r)+hedgeUnion _ cmplo cmphi Tip (Bin _ kx x l r) = join kx x (filterGt cmplo l) (filterLt cmphi r)-hedgeUnionWithKey f cmplo cmphi (Bin _ kx x l r) t2- = joinMaybe kx newx (hedgeUnionWithKey f cmplo cmpkx l lt) - (hedgeUnionWithKey f cmpkx cmphi r gt)+hedgeUnion f cmplo cmphi (Bin _ kx x l r) t2+ = joinMaybe kx newx (hedgeUnion f cmplo cmpkx l lt) + (hedgeUnion f cmpkx cmphi r gt) where cmpkx k = compare kx k lt = trim cmplo cmpkx t2 (found,gt) = trimLookupLo kx cmphi t2 newx = case found of Nothing -> Just x- Just (_,y) -> f kx x y+ Just (_,y) -> f x y filterGt :: (Ord k, Sized a) => (k -> Ordering) -> OrdMap k a -> OrdMap k a filterGt _ Tip = Tip@@ -236,35 +234,35 @@ GT -> trimLookupLo lo cmphi r EQ -> (Just (kx,x),trim (compare lo) cmphi r) -isect :: (Ord k, Sized a, Sized b, Sized c) => IsectFunc k a b c -> OrdMap k a -> OrdMap k b -> OrdMap k c+isect :: (Ord k, Sized a, Sized b, Sized c) => (a -> b -> Maybe c) -> OrdMap k a -> OrdMap k b -> OrdMap k c isect f t1@Bin{} (Bin _ k2 x2 l2 r2) - | (# found, hole #) <- search k2 Root t1- = let tl = isect f (beforeM Nothing hole) l2- tr = isect f (afterM Nothing hole) r2- in joinMaybe k2 (found >>= \ x1' -> f k2 x1' x2) tl tr+ = joinMaybe k2 (found >>= \ x1' -> f x1' x2) tl tr+ where !(# found, hole #) = search k2 Root t1+ tl = isect f (beforeM Nothing hole) l2+ tr = isect f (afterM Nothing hole) r2 isect _ _ _ = Tip -hedgeDiffWithKey :: (Ord k, Sized a)- => (k -> a -> b -> Maybe a)+hedgeDiff :: (Ord k, Sized a)+ => (a -> b -> Maybe a) -> (k -> Ordering) -> (k -> Ordering) -> OrdMap k a -> OrdMap k b -> OrdMap k a-hedgeDiffWithKey _ _ _ Tip _+hedgeDiff _ _ _ Tip _ = Tip-hedgeDiffWithKey _ cmplo cmphi (Bin _ kx x l r) Tip+hedgeDiff _ cmplo cmphi (Bin _ kx x l r) Tip = join kx x (filterGt cmplo l) (filterLt cmphi r)-hedgeDiffWithKey f cmplo cmphi t (Bin _ kx x l r) +hedgeDiff f cmplo cmphi t (Bin _ kx x l r) = case found of Nothing -> merge tl tr Just (ky,y) -> - case f ky y x of+ case f y x of Nothing -> merge tl tr Just z -> join ky z tl tr where cmpkx k = compare kx k lt = trim cmplo cmpkx t (found,gt) = trimLookupLo kx cmphi t- tl = hedgeDiffWithKey f cmplo cmpkx lt l- tr = hedgeDiffWithKey f cmpkx cmphi gt r+ tl = hedgeDiff f cmplo cmpkx lt l+ tr = hedgeDiff f cmpkx cmphi gt r joinMaybe :: (Ord k, Sized a) => k -> Maybe a -> OrdMap k a -> OrdMap k a -> OrdMap k a joinMaybe kx = maybe merge (join kx)@@ -310,24 +308,22 @@ glue Tip r = r glue l Tip = l glue l r- | size# l ># size# r = case deleteFindMax (\ k a -> (# balance k a, Nothing #)) l of- (# f, l' #) -> f l' r- | otherwise = case deleteFindMin (\ k a -> (# balance k a, Nothing #)) r of- (# f, r' #) -> f l r'+ | size# l ># size# r = let !(# f, l' #) = deleteFindMax (\ k a -> (# balance k a, Nothing #)) l in f l' r+ | otherwise = let !(# f, r' #) = deleteFindMin (\ k a -> (# balance k a, Nothing #)) r in f l r' deleteFindMin :: Sized a => (k -> a -> (# x, Maybe a #)) -> OrdMap k a -> (# x, OrdMap k a #) deleteFindMin f t = case t of- Bin _ k x Tip r -> onUnboxed (maybe r (\ y' -> bin k y' Tip r)) (f k) x- Bin _ k x l r -> onUnboxed (\ l' -> balance k x l' r) (deleteFindMin f) l- _ -> (# error "Map.deleteFindMin: can not return the minimal element of an empty map", Tip #)+ Bin _ k x Tip r -> onSnd (maybe r (\ y' -> bin k y' Tip r)) (f k) x+ Bin _ k x l r -> onSnd (\ l' -> balance k x l' r) (deleteFindMin f) l+ _ -> (# error "Map.deleteFindMin: can not return the minimal element of an empty fmap", Tip #) deleteFindMax :: Sized a => (k -> a -> (# x, Maybe a #)) -> OrdMap k a -> (# x, OrdMap k a #) deleteFindMax f t = case t of- Bin _ k x l Tip -> onUnboxed (maybe l (\ y -> bin k y l Tip)) (f k) x- Bin _ k x l r -> onUnboxed (balance k x l) (deleteFindMax f) r- Tip -> (# error "Map.deleteFindMax: can not return the maximal element of an empty map", Tip #)+ Bin _ k x l Tip -> onSnd (maybe l (\ y -> bin k y l Tip)) (f k) x+ Bin _ k x l r -> onSnd (balance k x l) (deleteFindMax f) r+ Tip -> (# error "Map.deleteFindMax: can not return the maximal element of an empty fmap", Tip #) size# :: OrdMap k a -> Int# size# Tip = 0#
Data/TrieMap/ProdMap.hs view
@@ -4,65 +4,65 @@ import Data.TrieMap.Sized import Data.TrieMap.TrieKey-import Data.TrieMap.Applicative import Control.Applicative -import Data.Foldable+import Data.Foldable hiding (foldlM, foldrM)+import Data.Monoid import Data.Sequence ((|>)) import qualified Data.Sequence as Seq instance (TrieKey k1, TrieKey k2) => TrieKey (k1, k2) where+ (k11, k12) =? (k21, k22) = k11 =? k21 && k12 =? k22+ (k11, k12) `cmp` (k21, k22) = (k11 `cmp` k21) `mappend` (k12 `cmp` k22)+ newtype TrieMap (k1, k2) a = PMap (TrieMap k1 (TrieMap k2 a)) data Hole (k1, k2) a = PHole (Hole k1 (TrieMap k2 a)) (Hole k2 a) emptyM = PMap emptyM- singletonM (k1, k2) a = PMap (singletonM k1 (singletonM k2 a))- nullM (PMap m) = nullM m+ singletonM (k1, k2) = PMap . singletonM k1 . singletonM k2+ getSimpleM (PMap m) = getSimpleM m >>= getSimpleM sizeM (PMap m) = sizeM m lookupM (k1, k2) (PMap m) = lookupM k1 m >>= lookupM k2- traverseWithKeyM f (PMap m) = PMap <$> traverseWithKeyM (\ a -> traverseWithKeyM (f . (a,))) m- foldrWithKeyM f (PMap m) = foldrWithKeyM (\ a -> foldrWithKeyM (f . (a,))) m- foldlWithKeyM f (PMap m) = foldlWithKeyM (\ a -> flip (foldlWithKeyM (f . (a,)))) m- mapWithKeyM f (PMap m) = PMap (mapWithKeyM (\ a -> mapWithKeyM (f . (a,))) m)- mapMaybeM f (PMap m) = PMap (mapMaybeM g m) where- g a = guardNullM . mapMaybeM (f . (a,))- mapEitherM f (PMap m) = both PMap PMap (mapEitherM g) m where- g a m = both guardNullM guardNullM (mapEitherM (f . (a,))) m+ traverseM f (PMap m) = PMap <$> traverseM (traverseM f) m+ foldrM f (PMap m) = foldrM (foldrM f) m+ foldlM f (PMap m) = foldlM (flip $ foldlM f) m+ fmapM f (PMap m) = PMap (fmapM (fmapM f) m)+ mapMaybeM f (PMap m) = PMap (mapMaybeM (mapMaybeM' f) m)+ mapEitherM f (PMap m) = both PMap PMap (mapEitherM (mapEitherM' f)) m isSubmapM (<=) (PMap m1) (PMap m2) = isSubmapM (isSubmapM (<=)) m1 m2- unionM f (PMap m1) (PMap m2) = PMap (unionM (\ a -> guardNullM .: unionM (f . (a,))) m1 m2)- isectM f (PMap m1) (PMap m2) = PMap (isectM (\ a -> guardNullM .: isectM (f . (a,))) m1 m2)- diffM f (PMap m1) (PMap m2) = PMap (diffM (\ a -> guardNullM .: diffM (f . (a,))) m1 m2)- fromListM f xs = PMap (mapWithKeyM (\ a (Elem xs) -> fromListM (f . (a,)) xs)- (fromListM (\ _ (Elem xs) (Elem ys) -> Elem (xs ++ ys)) (breakFst xs)))+ unionM f (PMap m1) (PMap m2) = PMap (unionM (unionM' f) m1 m2)+ isectM f (PMap m1) (PMap m2) = PMap (isectM (isectM' f) m1 m2)+ diffM f (PMap m1) (PMap m2) = PMap (diffM (diffM' f) m1 m2) fromAscListM f xs = PMap (fromDistAscListM- [(a, fromAscListM (f . (a,)) ys) | (a, Elem ys) <- breakFst xs])+ [(a, fromAscListM f ys) | (a, Elem ys) <- breakFst xs])+ fromDistAscListM xs = PMap (fromDistAscListM+ [(a, fromDistAscListM ys) | (a, Elem ys) <- breakFst xs]) singleHoleM (k1, k2) = PHole (singleHoleM k1) (singleHoleM k2)- keyM (PHole hole1 hole2) = (keyM hole1, keyM hole2)- assignM v (PHole hole1 hole2) = PMap (assignM (assignM v hole2) hole1)- clearM (PHole hole1 hole2) = PMap (fillHoleM (guardNullM (clearM hole2)) hole1)- beforeM a (PHole hole1 hole2) - = PMap (beforeM (guardNullM (beforeM a hole2)) hole1)- afterM a (PHole hole1 hole2)- = PMap (afterM (guardNullM (afterM a hole2)) hole1)- searchM (k1, k2) (PMap m) = case searchM k1 m of- (# Nothing, hole1 #) -> (# Nothing, PHole hole1 (singleHoleM k2) #)- (# Just m', hole1 #) -> onUnboxed (PHole hole1) (searchM k2) m'- indexM i (PMap m)- | (# i', m', hole1 #) <- indexM i m,- (# i'', v, hole2 #) <- indexM i' m'- = (# i'', v, PHole hole1 hole2 #)+ assignM v (PHole hole1 hole2) = PMap (assignM (assignM' v hole2) hole1)+ beforeM a (PHole hole1 hole2) = PMap (beforeM (beforeM' a hole2) hole1)+ afterM a (PHole hole1 hole2) = PMap (afterM (afterM' a hole2) hole1)+ searchM (k1, k2) (PMap m) = onSnd (PHole hole1) (searchM' k2) m'+ where !(# m', hole1 #) = searchM k1 m+ indexM i (PMap m) = onThird (PHole hole1) (indexM i') m'+ where !(# i', m', hole1 #) = indexM i m extractHoleM (PMap m) = do (m', hole1) <- extractHoleM m (v, hole2) <- extractHoleM m' return (v, PHole hole1 hole2)+ + unifyM (k11, k12) a1 (k21, k22) a2 = case unifyM k11 (singletonM k12 a1) k21 (singletonM k22 a2) of+ Left hole -> case unifyM k12 a1 k22 a2 of+ Left hole' -> Left (PHole hole hole')+ Right m' -> Right (PMap (assignM (Just m') hole))+ Right m -> Right (PMap m) -breakFst :: Eq k1 => [((k1, k2), a)] -> [(k1, Elem [(k2, a)])]+breakFst :: TrieKey k1 => [((k1, k2), a)] -> [(k1, Elem [(k2, a)])] breakFst [] = [] breakFst (((a, b),v):xs) = breakFst' a (Seq.singleton (b, v)) xs where breakFst' a vs (((a', b'), v'):xs)- | a == a' = breakFst' a' (vs |> (b', v')) xs+ | a =? a' = breakFst' a' (vs |> (b', v')) xs | otherwise = (a, Elem $ toList vs):breakFst' a' (Seq.singleton (b', v')) xs breakFst' a vs [] = [(a, Elem $ toList vs)]
Data/TrieMap/RadixTrie.hs view
@@ -1,267 +1,128 @@-{-# LANGUAGE BangPatterns, UnboxedTuples, TupleSections, TypeFamilies, PatternGuards, MagicHash #-}+{-# LANGUAGE BangPatterns, UnboxedTuples, TypeFamilies, MagicHash, FlexibleInstances #-} module Data.TrieMap.RadixTrie () where import Data.TrieMap.TrieKey import Data.TrieMap.Sized--- import Data.TrieMap.Applicative import Control.Applicative import Control.Monad +import Foreign.Storable+ import Data.Maybe+import Data.Monoid+import Data.Ord import Data.Foldable (foldr, foldl)+import Data.Vector.Generic hiding (Vector, cmp, foldl, foldr)+import Data.Vector (Vector)+import qualified Data.Vector as V+import qualified Data.Vector.Storable as S import Data.Traversable--import GHC.Exts--import Prelude hiding (lookup, foldr, foldl)+import Data.Word -data Assoc k a = Empty | Assoc [k] a-data Edge k a = Edge Int# [k] (Assoc k a) (TrieMap k (Edge k a))-type MEdge k a = Maybe (Edge k a)+import Data.TrieMap.RadixTrie.Slice+import Data.TrieMap.RadixTrie.Edge -instance Sized (Edge k a) where- getSize# (Edge sz _ _ _) = sz+import Prelude hiding (length, and, zip, zipWith, foldr, foldl) -instance Sized a => Sized (Assoc k a) where- getSize# (Assoc _ a) = getSize# a- getSize# _ = 0#+instance TrieKey k => TrieKey (Vector k) where+ ks =? ls = length ks == length ls && and (zipWith (=?) ks ls)+ ks `cmp` ls = V.foldr (\ (k, l) z -> (k `cmp` l) `mappend` z) (comparing length ks ls) (zip ks ls) -data Path k a = Root- | Deep (Path k a) [k] (Assoc k a) (Hole k (Edge k a))+ newtype TrieMap (Vector k) a = Radix (MEdge Vector k a)+ newtype Hole (Vector k) a = Hole (EdgeLoc Vector k a)+ + emptyM = Radix Nothing+ singletonM ks a = Radix (Just (singletonEdge (v2S ks) a))+ getSimpleM (Radix Nothing) = Null+ getSimpleM (Radix (Just e)) = getSimpleEdge e+ sizeM (Radix m) = getSize# m+ lookupM ks (Radix m) = m >>= lookupEdge ks -instance TrieKey k => TrieKey [k] where- newtype TrieMap [k] a = Radix (MEdge k a)- data Hole [k] a = Hole [k] [k] (TrieMap k (Edge k a)) (Path k a)+ fmapM f (Radix m) = Radix (mapEdge f <$> m)+ mapMaybeM f (Radix m) = Radix (m >>= mapMaybeEdge f)+ mapEitherM f (Radix e) = both Radix Radix (mapEitherMaybe (mapEitherEdge f)) e+ traverseM f (Radix m) = Radix <$> traverse (traverseEdge f) m - emptyM = Radix Nothing- singletonM ks a = Radix (Just (Edge (getSize# a) ks (Assoc ks a) emptyM))- nullM (Radix m) = isNothing m- sizeM (Radix (Just e)) = getSize# e- sizeM _ = 0#- lookupM ks (Radix m) = m >>= lookup ks- traverseWithKeyM f (Radix m) = Radix <$> traverse (traverseE f) m- foldrWithKeyM f (Radix m) z = foldr (foldrE f) z m- foldlWithKeyM f (Radix m) z = foldl (foldlE f) z m- mapWithKeyM f (Radix m) = Radix (mapWithKeyE f <$> m)- mapMaybeM f (Radix m) = Radix (m >>= mapMaybeE f)- mapEitherM _ (Radix Nothing) = (# emptyM, emptyM #)- mapEitherM f (Radix (Just m)) = both Radix Radix (mapEitherE f) m- unionM f (Radix m1) (Radix m2) = Radix (unionMaybe (unionE f) m1 m2)- isectM f (Radix m1) (Radix m2) = Radix (isectMaybe (isectE f) m1 m2)- diffM f (Radix m1) (Radix m2) = Radix (diffMaybe (diffE f) m1 m2)- isSubmapM (<=) (Radix m1) (Radix m2) = subMaybe (isSubmapE (<=)) m1 m2+ foldrM f (Radix m) z = foldr (foldrEdge f) z m+ foldlM f (Radix m) z = foldl (foldlEdge f) z m - singleHoleM ks = Hole ks ks emptyM Root- keyM (Hole ks _ _ _) = ks- beforeM a (Hole ks0 ks ts path) = before (compact (edge ks v ts)) path where- v = case a of- Nothing -> Empty- Just a -> Assoc ks0 a- before t Root = Radix t- before e (Deep path ks v tHole) =- before (compact $ edge ks v $ beforeM e tHole) path- afterM a (Hole ks0 ks ts path) = after (compact (edge ks v ts)) path where- v = case a of- Nothing -> Empty- Just a -> Assoc ks0 a- after t Root = Radix t- after e (Deep path ks v tHole) =- after (compact $ edge ks v $ afterM e tHole) path+ unionM f (Radix m1) (Radix m2) = Radix (unionMaybe (unionEdge f) m1 m2)+ isectM f (Radix m1) (Radix m2) = Radix (isectMaybe (isectEdge f) m1 m2)+ diffM f (Radix m1) (Radix m2) = Radix (diffMaybe (diffEdge f) m1 m2)+ + isSubmapM (<=) (Radix m1) (Radix m2) = subMaybe (isSubEdge (<=)) m1 m2 - searchM ks (Radix Nothing) = (# Nothing, singleHoleM ks #)- searchM ks (Radix (Just e)) = case searchE ks e Root of- (# v, holer #) -> (# v, holer ks #)+ singleHoleM ks = Hole (singleLoc (v2S ks))+ searchM ks (Radix (Just e)) = case searchEdge (v2S ks) e Root of+ (a, loc) -> (# a, Hole loc #)+ searchM ks _ = (# Nothing, singleHoleM ks #)+ indexM i (Radix (Just e)) = case indexEdge i e Root of+ (# i', a, loc #) -> (# i', a, Hole loc #)+ indexM _ (Radix Nothing) = indexFail () - indexM _ (Radix Nothing) = (# error err, error err, error err #)- where err = "Error: trie map is empty"- indexM i# (Radix (Just e)) = indexE i# e Root+ assignM a (Hole loc) = Radix (fillHoleEdge a loc) - extractHoleM (Radix Nothing) = mzero- extractHoleM (Radix (Just e)) = extractHoleE Root e+ extractHoleM (Radix (Just e)) = do+ (a, loc) <- extractEdgeLoc e Root+ return (a, Hole loc)+ extractHoleM _ = mzero - assignM a (Hole ks0 ks ts path) = Radix $ rebuild (compact (edge ks (Assoc ks0 a) ts)) path+ beforeM a (Hole loc) = Radix (beforeEdge a loc)+ afterM a (Hole loc) = Radix (afterEdge a loc) - clearM (Hole _ ks ts path) = Radix $ rebuild (compact (edge ks Empty ts)) path--rebuild :: (TrieKey k, Sized a) => MEdge k a -> Path k a -> MEdge k a-rebuild e (Deep path ks v tHole) =- rebuild (compact (edge ks v (fillHoleM e tHole))) path-rebuild e _ = e--cat :: [k] -> Edge k a -> Edge k a-ks `cat` Edge sz ls v ts = Edge sz (ks ++ ls) v ts--cons :: k -> Edge k a -> Edge k a-k `cons` Edge sz ks v ts = Edge sz (k:ks) v ts--edge :: (TrieKey k, Sized a) => [k] -> Assoc k a -> TrieMap k (Edge k a) -> Edge k a-edge ks v ts = Edge (getSize# v +# getSize# ts) ks v ts--compact :: TrieKey k => Edge k a -> MEdge k a-compact e@(Edge _ ks Empty ts) = case assocsM ts of- [] -> Nothing- [(l, e')] -> compact (ks `cat` (l `cons` e'))- _ -> Just e-compact e = Just e--lookup :: (Eq k, TrieKey k) => [k] -> Edge k a -> Maybe a-lookup ks (Edge _ ls v ts) = match ks ls where- match (k:ks) (l:ls)- | k == l = match ks ls- match (k:ks) [] = lookupM k ts >>= lookup ks- match [] [] = case v of- Assoc _ a -> Just a- _ -> Nothing- match _ _ = Nothing--traverseA :: Applicative f => ([k] -> a -> f b) -> Assoc k a -> f (Assoc k b)-traverseA f (Assoc ks a) = Assoc ks <$> f ks a-traverseA _ _ = pure Empty--traverseE :: (Applicative f, TrieKey k, Sized b) => ([k] -> a -> f b) -> Edge k a -> f (Edge k b)-traverseE f (Edge _ ks v ts)- = edge ks <$> traverseA f v <*> traverseM (traverseE f) ts--foldrA :: ([k] -> a -> b -> b) -> Assoc k a -> b -> b-foldrA f (Assoc ks a) = f ks a-foldrA _ _ = id--foldlA :: ([k] -> b -> a -> b) -> b -> Assoc k a -> b-foldlA f z (Assoc ks a) = f ks z a-foldlA _ z _ = z--foldrE :: TrieKey k => ([k] -> a -> b -> b) -> Edge k a -> b -> b-foldrE f (Edge _ _ v ts) z = foldrA f v (foldr (foldrE f) z ts)--foldlE :: TrieKey k => ([k] -> b -> a -> b) -> b -> Edge k a -> b -foldlE f z (Edge _ _ v ts) = foldl (foldlE f) (foldlA f z v) ts--mapWithKeyA :: ([k] -> a -> b) -> Assoc k a -> Assoc k b-mapWithKeyA f (Assoc ks a) = Assoc ks (f ks a)-mapWithKeyA _ _ = Empty--mapWithKeyE :: (TrieKey k, Sized b) => ([k] -> a -> b) -> Edge k a -> Edge k b-mapWithKeyE f (Edge _ ks v ts) = edge ks (mapWithKeyA f v) (fmapM (mapWithKeyE f) ts)--mapMaybeA :: ([k] -> a -> Maybe b) -> Assoc k a -> Assoc k b-mapMaybeA f (Assoc ks a) = maybe Empty (Assoc ks) (f ks a)-mapMaybeA _ _ = Empty--mapMaybeE :: (TrieKey k, Sized b) => ([k] -> a -> Maybe b) -> Edge k a -> MEdge k b-mapMaybeE f (Edge _ ks v ts) = compact (edge ks (mapMaybeA f v)- (mapMaybeM (const $ mapMaybeE f) ts))--mapEitherA :: ([k] -> a -> (# Maybe b, Maybe c #)) -> Assoc k a -> (# Assoc k b, Assoc k c #)-mapEitherA f (Assoc ks a) = case f ks a of- (# vL, vR #) -> (# maybe Empty (Assoc ks) vL, maybe Empty (Assoc ks) vR #)-mapEitherA _ _ = (# Empty, Empty #)--mapEitherE :: (TrieKey k, Sized b, Sized c) => ([k] -> a -> (# Maybe b, Maybe c #)) -> Edge k a ->- (# MEdge k b, MEdge k c #)-mapEitherE f (Edge _ ks v ts) = case mapEitherA f v of- (# vL, vR #) -> case mapEitherM (\ _ -> mapEitherE f) ts of- (# tsL, tsR #) -> (# compact (edge ks vL tsL), compact (edge ks vR tsR) #)--unionE :: (TrieKey k, Sized a) => ([k] -> a -> a -> Maybe a) -> Edge k a -> Edge k a -> MEdge k a-unionE f (Edge szK# ks0 vK tsK) (Edge szL# ls0 vL tsL) = match 0 ks0 ls0 where- match !i (k:ks) (l:ls) = case compare k l of- EQ -> match (i+1) ks ls- LT -> Just $ Edge (szK# +# szL#) (take i ks0) Empty (fromDistAscListM - [(k, Edge szK# ks vK tsK), (l, Edge szL# ls vL tsL)])- GT -> Just $ Edge (szK# +# szL#) (take i ks0) Empty (fromDistAscListM- [(l, Edge szL# ls vL tsL), (k, Edge szK# ks vK tsK)])- match _ [] (l:ls) = compact (edge ks0 vK (alterM g l tsK)) where- g (Just eK') = unionE f eK' (Edge szL# ls vL tsL)- g Nothing = Just (Edge szL# ls vL tsL)- match _ (k:ks) [] = compact (edge ls0 vL (alterM g k tsL)) where- g Nothing = Just (Edge szK# ks vK tsK)- g (Just eL') = unionE f (Edge szK# ks vK tsK) eL'- match _ [] [] = compact (edge ls0 (unionA f vK vL) (unionM (const $ unionE f) tsK tsL))--unionA :: ([k] -> a -> a -> Maybe a) -> Assoc k a -> Assoc k a -> Assoc k a-unionA f (Assoc ks v1) (Assoc _ v2) = maybe Empty (Assoc ks) (f ks v1 v2)-unionA _ Empty v = v-unionA _ v Empty = v+ unifyM ks1 a1 ks2 a2 = either (Left . Hole) (Right . Radix . Just) (unifyEdge (v2S ks1) a1 (v2S ks2) a2) -isectE :: (TrieKey k, Sized c) => ([k] -> a -> b -> Maybe c) -> Edge k a -> Edge k b -> MEdge k c-isectE f (Edge szK ks0 vK tsK) (Edge szL ls0 vL tsL) = match ks0 ls0 where- match (k:ks) (l:ls)- | k == l = match ks ls- match (k:ks) [] = do eL' <- lookupM k tsL- cat ls0 <$> cons k <$> isectE f (Edge szK ks vK tsK) eL'- match [] (l:ls) = do eK' <- lookupM l tsK- cat ks0 <$> cons l <$> isectE f eK' (Edge szL ls vL tsL)- match [] [] = compact (edge ks0 (isectA f vK vL) (isectM (const $ isectE f) tsK tsL))- match _ _ = Nothing+type WordVec = S.Vector Word -isectA :: ([k] -> a -> b -> Maybe c) -> Assoc k a -> Assoc k b -> Assoc k c-isectA f (Assoc ks a) (Assoc _ b) = maybe Empty (Assoc ks) (f ks a b)-isectA _ _ _ = Empty+vZipWith :: (Storable a, Storable b) => (a -> b -> c) -> S.Vector a -> S.Vector b -> Vector c+vZipWith f xs ys = V.zipWith f (convert xs) (convert ys) -diffE :: (TrieKey k, Sized a) => ([k] -> a -> b -> Maybe a) -> Edge k a -> Edge k b -> MEdge k a-diffE f eK@(Edge szK ks0 vK tsK) (Edge szL ls0 vL tsL) = match ks0 ls0 where- match (k:ks) (l:ls)- | k == l = match ks ls- match (k:ks) []- | Just eL' <- lookupM k tsL- = cat ls0 . cons k <$> diffE f (Edge szK ks vK tsK) eL'- match [] (l:ls)- = compact (edge ks0 vK (alterM (>>= g) l tsK))- where g eK' = diffE f eK' (Edge szL ls vL tsL)- match [] [] = compact (edge ks0 (diffA f vK vL) (diffM (const $ diffE f) tsK tsL))- match _ _ = Just eK+instance TrieKey (S.Vector Word) where+ ks =? ls = length ks == length ls && and (vZipWith (=?) ks ls)+ ks `cmp` ls = V.foldr (\ (k, l) z -> (k `cmp` l) `mappend` z) (comparing length ks ls) (vZipWith (,) ks ls) -diffA :: ([k] -> a -> b -> Maybe a) -> Assoc k a -> Assoc k b -> Assoc k a-diffA f (Assoc ks a) (Assoc _ b) = maybe Empty (Assoc ks) (f ks a b)-diffA _ a@Assoc{} Empty = a-diffA _ Empty _ = Empty+ newtype TrieMap WordVec a = WRadix (MEdge S.Vector Word a)+ newtype Hole WordVec a = WHole (EdgeLoc S.Vector Word a)+ + emptyM = WRadix Nothing+ singletonM ks a = WRadix (Just (singletonEdge (v2S ks) a))+ getSimpleM (WRadix Nothing) = Null+ getSimpleM (WRadix (Just e)) = getSimpleEdge e+ sizeM (WRadix m) = getSize# m+ lookupM ks (WRadix m) = m >>= lookupEdge ks -isSubmapE :: TrieKey k => LEq a b -> LEq (Edge k a) (Edge k b)-isSubmapE (<=) (Edge szK ks vK tsK) (Edge _ ls vL tsL) = match ks ls where- match (k:ks) (l:ls)- | k == l = match ks ls- match (k:ks) []- | Just eL' <- lookupM k tsL- = isSubmapE (<=) (Edge szK ks vK tsK) eL'- match [] [] = subA (<=) vK vL && isSubmapM (isSubmapE (<=)) tsK tsL- match _ _ = False+ fmapM f (WRadix m) = WRadix (mapEdge f <$> m)+ mapMaybeM f (WRadix m) = WRadix (m >>= mapMaybeEdge f)+ mapEitherM f (WRadix e) = both WRadix WRadix (mapEitherMaybe (mapEitherEdge f)) e+ traverseM f (WRadix m) = WRadix <$> traverse (traverseEdge f) m -subA :: LEq a b -> LEq (Assoc k a) (Assoc k b)-subA (<=) (Assoc _ a) (Assoc _ b) = a <= b-subA _ Assoc{} Empty = False-subA _ Empty _ = True+ foldrM f (WRadix m) z = foldr (foldrEdge f) z m+ foldlM f (WRadix m) z = foldl (foldlEdge f) z m -searchE :: TrieKey k => [k] -> Edge k a -> Path k a -> (# Maybe a, [k] -> Hole [k] a #)-searchE ks0 (Edge sz ls0 v ts) path = match 0 ks0 ls0 where- match !_ [] [] = (# assocToMaybe v, \ k0 -> Hole k0 ls0 ts path #)- match _ (k:ks) [] = case searchM k ts of- (# Just e', tHole #) -> searchE ks e' (Deep path ls0 v tHole)- (# Nothing, tHole #) -> (# Nothing, \ k0 -> Hole k0 ks emptyM (Deep path ls0 v tHole) #)- match i [] (l:ls) = (# Nothing, \ k0 -> Hole k0 (take i ls0) (singletonM l (Edge sz ls v ts)) path #)- match i (k:ks) (l:ls)- | k == l = match (i+1) ks ls- | (# _, kHole #) <- searchM k (singletonM l (Edge sz ls v ts))- = (# Nothing, \ k0 -> Hole k0 ks emptyM (Deep path (take i ls0) Empty kHole) #)+ unionM f (WRadix m1) (WRadix m2) = WRadix (unionMaybe (unionEdge f) m1 m2)+ isectM f (WRadix m1) (WRadix m2) = WRadix (isectMaybe (isectEdge f) m1 m2)+ diffM f (WRadix m1) (WRadix m2) = WRadix (diffMaybe (diffEdge f) m1 m2)+ + isSubmapM (<=) (WRadix m1) (WRadix m2) = subMaybe (isSubEdge (<=)) m1 m2 -assocToMaybe :: Assoc k a -> Maybe a-assocToMaybe (Assoc _ a) = Just a-assocToMaybe _ = Nothing+ singleHoleM ks = WHole (singleLoc (v2S ks))+ searchM ks (WRadix (Just e)) = case searchEdge (v2S ks) e Root of+ (a, loc) -> (# a, WHole loc #)+ searchM ks _ = (# Nothing, singleHoleM ks #)+ indexM i (WRadix (Just e)) = case indexEdge i e Root of+ (# i', a, loc #) -> (# i', a, WHole loc #)+ indexM _ (WRadix Nothing) = indexFail () -indexE :: (TrieKey k, Sized a) => Int# -> Edge k a -> Path k a -> (# Int#, a, Hole [k] a #)-indexE i# (Edge _ ks Empty ts) path- | (# i'#, e, tHole #) <- indexM i# ts- = indexE i'# e (Deep path ks Empty tHole)-indexE i# (Edge _ ks v@(Assoc ks0 a) ts) path- | i# <# sa# = (# i#, a, Hole ks0 ks ts path #)- | (# i'#, e, tHole #) <- indexM (i# -# sa#) ts- = indexE i'# e (Deep path ks v tHole)- where !sa# = getSize# a+ assignM a (WHole loc) = WRadix (fillHoleEdge a loc)+ + extractHoleM (WRadix (Just e)) = do+ (a, loc) <- extractEdgeLoc e Root+ return (a, WHole loc)+ extractHoleM _ = mzero -extractHoleE :: (TrieKey k, MonadPlus m) => Path k a -> Edge k a -> m (a, Hole [k] a)-extractHoleE path (Edge _ ks v ts) = case v of- Empty -> tsHoles- Assoc ks0 a -> return (a, Hole ks0 ks ts path) `mplus` tsHoles- where tsHoles = do (e, tHole) <- extractHoleM ts- extractHoleE (Deep path ks v tHole) e+ beforeM a (WHole loc) = WRadix (beforeEdge a loc)+ afterM a (WHole loc) = WRadix (afterEdge a loc)+ + unifyM ks1 a1 ks2 a2 = either (Left . WHole) (Right . WRadix . Just) (unifyEdge (v2S ks1) a1 (v2S ks2) a2)
+ Data/TrieMap/RadixTrie/Edge.hs view
@@ -0,0 +1,269 @@+{-# LANGUAGE MagicHash, BangPatterns, UnboxedTuples, PatternGuards, CPP #-}+{-# OPTIONS -funbox-strict-fields #-}+module Data.TrieMap.RadixTrie.Edge where++import Data.TrieMap.Sized+import Data.TrieMap.TrieKey+import Data.TrieMap.RadixTrie.Slice+import Data.TrieMap.IntMap ()+import Data.TrieMap.Applicative ()++import Control.Applicative+import Control.Monad+import Data.Word+import Data.Traversable+import Data.Foldable (foldr, foldl)++import Data.Vector.Generic hiding (indexM, cmp, foldr, foldl)+import qualified Data.Vector+import qualified Data.Vector.Storable+import Prelude hiding (length, foldr, foldl, zip, take)++import GHC.Exts++#define V(f) f (Data.Vector.Vector) (k)+#define U(f) f (Data.Vector.Storable.Vector) (Word)++type Branch v k a = TrieMap k (Edge v k a)+data Edge v k a =+ Edge Int# !(Slice v k) !(Maybe a) (Branch v k a)+data EdgeLoc v k a = Loc !(Slice v k) (Branch v k a) (Path v k a)+data Path v k a = Root+ | Deep (Path v k a) !(Slice v k) !(Maybe a) (Hole k (Edge v k a))+type MEdge v k a = Maybe (Edge v k a)++instance Sized (Edge v k a) where+ getSize# (Edge s# _ _ _) = s#++{-# SPECIALIZE singleLoc :: U(Slice) -> U(EdgeLoc) a #-}+singleLoc :: TrieKey k => Slice v k -> EdgeLoc v k a+singleLoc ks = Loc ks emptyM Root++{-# SPECIALIZE singletonEdge :: Sized a => U(Slice) -> a -> U(Edge) a #-}+singletonEdge :: (TrieKey k, Sized a) => Slice v k -> a -> Edge v k a+singletonEdge ks a = edge ks (Just a) emptyM++{-# SPECIALIZE getSimpleEdge :: U(Edge) a -> Simple a #-}+getSimpleEdge :: TrieKey k => Edge v k a -> Simple a+getSimpleEdge (Edge _ _ v ts)+ | nullM ts = maybe Null Singleton v+ | otherwise = NonSimple++{-# SPECIALIZE edge :: Sized a => U(Slice) -> Maybe a -> U(Branch) a -> U(Edge) a #-}+edge :: (TrieKey k, Sized a) => Slice v k -> Maybe a -> Branch v k a -> Edge v k a+edge ks v ts = Edge (getSize# v +# sizeM ts) ks v ts++{-# INLINE compact #-}+-- TODO: figure out a way to GC dead keys+compact :: TrieKey k => Edge v k a -> MEdge v k a+compact e@(Edge _ ks Nothing ts) = case getSimpleM ts of+ Null -> Nothing+ Singleton e' -> Just (unDropEdge (len ks + 1) e')+ _ -> Just e+compact e = Just e++dropEdge :: Int -> Edge v k a -> Edge v k a+dropEdge n (Edge s# ks v ts) = Edge s# (dropSlice n ks) v ts++unDropEdge :: Int -> Edge v k a -> Edge v k a+unDropEdge n (Edge s# ks v ts) = Edge s# (unDropSlice n ks) v ts++{-# SPECIALIZE lookupEdge :: TrieKey k => V() -> V(Edge) a -> Maybe a #-}+{-# SPECIALIZE lookupEdge :: U() -> U(Edge) a -> Maybe a #-}+lookupEdge :: (TrieKey k, Vector v k) => v k -> Edge v k a -> Maybe a+lookupEdge = lookupE where+ lookupE !ks (Edge _ ls v ts) = if kLen < lLen then Nothing else matchSliceV matcher matches ks ls where+ !kLen = length ks+ !lLen = len ls+ matcher k l z+ | k =? l = z+ | otherwise = Nothing+ matches _ _+ | kLen == lLen = v+ | otherwise = do e' <- lookupM (ks `unsafeIndex` lLen) ts+ lookupE (unsafeDrop (lLen + 1) ks) e'++{-# SPECIALIZE searchEdge :: TrieKey k => V(Slice) -> V(Edge) a -> V(Path) a -> (Maybe a, V(EdgeLoc) a) #-}+{-# SPECIALIZE searchEdge :: U(Slice) -> U(Edge) a -> U(Path) a -> (Maybe a, U(EdgeLoc) a) #-}+searchEdge :: (TrieKey k, Vector v k) => Slice v k -> Edge v k a -> Path v k a -> (Maybe a, EdgeLoc v k a)+searchEdge = searchE where+ searchE !ks e@(Edge _ ls v ts) path = iMatchSlice matcher matches ks ls where+ matcher i k l z+ | k =? l = z+ | (# _, tHole #) <- searchM k (singletonM l (dropEdge (i+1) e))+ = (Nothing, Loc (dropSlice (i+1) ks) emptyM (Deep path (takeSlice i ls) Nothing tHole))+ matches kLen lLen = case compare kLen lLen of+ EQ -> (v, Loc ls ts path)+ LT -> let (lPre, !l, _) = splitSlice kLen ls in + (Nothing, Loc lPre (singletonM l (dropEdge (kLen + 1) e)) path)+ GT -> let (_, !k, ks') = splitSlice lLen ks in case searchM k ts of+ (# Nothing, tHole #) -> (Nothing, Loc ks' emptyM (Deep path ls v tHole))+ (# Just e', tHole #) -> searchE ks' e' (Deep path ls v tHole)++{-# SPECIALIZE mapEdge :: Sized b => (a -> b) -> U(Edge) a -> U(Edge) b #-}+mapEdge :: (TrieKey k, Sized b) => (a -> b) -> Edge v k a -> Edge v k b+mapEdge f = mapE where+ mapE (Edge _ ks v ts) = edge ks (f <$> v) (fmapM mapE ts)++{-# SPECIALIZE mapMaybeEdge :: Sized b => (a -> Maybe b) -> U(Edge) a -> U(MEdge) b #-}+mapMaybeEdge :: (TrieKey k, Sized b) => (a -> Maybe b) -> Edge v k a -> MEdge v k b+mapMaybeEdge f = mapMaybeE where+ mapMaybeE (Edge _ ks v ts) = compact (edge ks (v >>= f) (mapMaybeM mapMaybeE ts))++{-# SPECIALIZE mapEitherEdge :: (Sized b, Sized c) =>+ (a -> (# Maybe b, Maybe c #)) -> U(Edge) a -> (# U(MEdge) b, U(MEdge) c #) #-}+mapEitherEdge :: (TrieKey k, Sized b, Sized c) => + (a -> (# Maybe b, Maybe c #)) -> Edge v k a -> (# MEdge v k b, MEdge v k c #)+mapEitherEdge f = mapEitherE where+ mapEitherE (Edge _ ks v ts) = (# compact (edge ks vL tsL), compact (edge ks vR tsR) #)+ where !(# vL, vR #) = mapEitherMaybe f v+ !(# tsL, tsR #) = mapEitherM mapEitherE ts++{-# SPECIALIZE traverseEdge :: (Applicative f, Sized b) =>+ (a -> f b) -> U(Edge) a -> f (U(Edge) b) #-}+traverseEdge :: (TrieKey k, Applicative f, Sized b) =>+ (a -> f b) -> Edge v k a -> f (Edge v k b)+traverseEdge f = traverseE where+ traverseE (Edge _ ks v ts) = edge ks <$> traverse f v <*> traverseM traverseE ts++{-# SPECIALIZE foldrEdge :: (a -> b -> b) -> U(Edge) a -> b -> b #-}+foldrEdge :: TrieKey k => (a -> b -> b) -> Edge v k a -> b -> b+foldrEdge f = foldrE where+ foldrE (Edge _ _ v ts) z = foldr f (foldrM foldrE ts z) v++foldlEdge :: TrieKey k => (b -> a -> b) -> b -> Edge v k a -> b+foldlEdge f = foldlE where+ foldlE z (Edge _ _ v ts) = foldlM foldlE ts (foldl f z v)++{-# SPECIALIZE rebuild :: Sized a => U(MEdge) a -> U(Path) a -> U(MEdge) a #-}+rebuild :: (TrieKey k, Sized a) => MEdge v k a -> Path v k a -> MEdge v k a+rebuild e Root = e+rebuild e (Deep path ks v tHole) = rebuild (compact $ edge ks v $ assignM e tHole) path++{-# SPECIALIZE fillHoleEdge :: Sized a => Maybe a -> U(EdgeLoc) a -> U(MEdge) a #-}+fillHoleEdge :: (TrieKey k, Sized a) => Maybe a -> EdgeLoc v k a -> MEdge v k a+fillHoleEdge v (Loc ks ts path) = rebuild (compact (edge ks v ts)) path++{-# SPECIALIZE unionEdge :: (TrieKey k, Sized a) => + (a -> a -> Maybe a) -> V(Edge) a -> V(Edge) a -> V(MEdge) a #-}+{-# SPECIALIZE unionEdge :: Sized a =>+ (a -> a -> Maybe a) -> U(Edge) a -> U(Edge) a -> U(MEdge) a #-}+unionEdge :: (TrieKey k, Vector v k, Sized a) => + (a -> a -> Maybe a) -> Edge v k a -> Edge v k a -> MEdge v k a+unionEdge f = unionE where+ eK@(Edge _ ks0 vK tsK) `unionE` eL@(Edge _ ls0 vL tsL) = iMatchSlice matcher matches ks0 ls0 where+ matcher i k l z = case unifyM k eK' l eL' of+ Left{} -> z+ Right ts -> Just (edge (takeSlice i ks0) Nothing ts)+ where eK' = dropEdge (i+1) eK+ eL' = dropEdge (i+1) eL+ matches kLen lLen = case compare kLen lLen of+ EQ -> compact $ edge ks0 (unionMaybe f vK vL) $ unionM unionE tsK tsL+ LT -> let eL' = dropEdge (kLen + 1) eL; l = ls0 !$ kLen; !(# eK', holeKT #) = searchM l tsK+ in compact $ edge ks0 vK $ assignM (maybe (Just eL') (`unionE` eL') eK') holeKT+ GT -> let eK' = dropEdge (lLen + 1) eK; k = ks0 !$ lLen; !(# eL', holeLT #) = searchM k tsL+ in compact $ edge ls0 vL $ assignM (maybe (Just eK') (eK' `unionE`) eL') holeLT++{-# SPECIALIZE isectEdge :: (TrieKey k, Sized c) =>+ (a -> b -> Maybe c) -> V(Edge) a -> V(Edge) b -> V(MEdge) c #-}+{-# SPECIALIZE isectEdge :: Sized c =>+ (a -> b -> Maybe c) -> U(Edge) a -> U(Edge) b -> U(MEdge) c #-}+isectEdge :: (TrieKey k, Vector v k, Sized c) =>+ (a -> b -> Maybe c) -> Edge v k a -> Edge v k b -> MEdge v k c+isectEdge f = isectE where+ eK@(Edge _ ks0 vK tsK) `isectE` eL@(Edge _ ls0 vL tsL) = matchSlice matcher matches ks0 ls0 where+ matcher k l z = guard (k =? l) >> z+ matches kLen lLen = case compare kLen lLen of+ EQ -> compact $ edge ks0 (isectMaybe f vK vL) $ isectM isectE tsK tsL+ LT -> let l = ls0 !$ kLen in do+ eK' <- lookupM l tsK+ let eL' = dropEdge (kLen + 1) eL+ unDropEdge (kLen + 1) <$> eK' `isectE` eL'+ GT -> let k = ks0 !$ lLen in do+ eL' <- lookupM k tsL+ let eK' = dropEdge (lLen + 1) eK+ unDropEdge (lLen + 1) <$> eK' `isectE` eL'++{-# SPECIALIZE diffEdge :: (TrieKey k, Sized a) =>+ (a -> b -> Maybe a) -> V(Edge) a -> V(Edge) b -> V(MEdge) a #-}+{-# SPECIALIZE diffEdge :: Sized a =>+ (a -> b -> Maybe a) -> U(Edge) a -> U(Edge) b -> U(MEdge) a #-}+diffEdge :: (TrieKey k, Vector v k, Sized a) =>+ (a -> b -> Maybe a) -> Edge v k a -> Edge v k b -> MEdge v k a+diffEdge f = diffE where+ eK@(Edge _ ks0 vK tsK) `diffE` eL@(Edge _ ls0 vL tsL) = matchSlice matcher matches ks0 ls0 where+ matcher k l z+ | k =? l = z+ | otherwise = Just eK+ matches kLen lLen = case compare kLen lLen of+ EQ -> compact $ edge ks0 (diffMaybe f vK vL) $ diffM diffE tsK tsL+ LT -> let l = ls0 !$ kLen; eL' = dropEdge (kLen + 1) eL in case searchM l tsK of+ (# Nothing, _ #) -> Just eK+ (# Just eK', holeKT #) -> compact $ edge ks0 vK $ assignM (eK' `diffE` eL') holeKT+ GT -> let k = ks0 !$ lLen; eK' = dropEdge (lLen + 1) eK in case lookupM k tsL of+ Nothing -> Just eK+ Just eL' -> fmap (unDropEdge (lLen + 1)) (eK' `diffE` eL')++{-# SPECIALIZE isSubEdge :: TrieKey k => LEq a b -> LEq (V(Edge) a) (V(Edge) b) #-}+{-# SPECIALIZE isSubEdge :: LEq a b -> LEq (U(Edge) a) (U(Edge) b) #-}+isSubEdge :: (TrieKey k, Vector v k) => LEq a b -> LEq (Edge v k a) (Edge v k b)+isSubEdge (<=) = isSubE where+ eK@(Edge _ ks0 vK tsK) `isSubE` (Edge _ ls0 vL tsL) = matchSlice matcher matches ks0 ls0 where+ matcher k l z = k =? l && z+ matches kLen lLen = case compare kLen lLen of+ LT -> False+ EQ -> subMaybe (<=) vK vL && isSubmapM isSubE tsK tsL+ GT -> let k = ks0 !$ lLen in case lookupM k tsL of+ Nothing -> False+ Just eL' -> isSubE (dropEdge (lLen + 1) eK) eL'++{-# SPECIALIZE beforeEdge :: Sized a => Maybe a -> U(EdgeLoc) a -> U(MEdge) a #-}+beforeEdge :: (TrieKey k, Sized a) => Maybe a -> EdgeLoc v k a -> MEdge v k a+beforeEdge v (Loc ks ts path) = buildBefore (compact (edge ks v ts)) path where+ buildBefore !e Root+ = e+ buildBefore e (Deep path ks v tHole)+ = buildBefore (compact $ edge ks v $ beforeM e tHole) path++{-# SPECIALIZE afterEdge :: Sized a => Maybe a -> U(EdgeLoc) a -> U(MEdge) a #-}+afterEdge :: (TrieKey k, Sized a) => Maybe a -> EdgeLoc v k a -> MEdge v k a+afterEdge v (Loc ks ts path) = buildAfter (compact (edge ks v ts)) path where+ buildAfter !e Root+ = e+ buildAfter e (Deep path ks v tHole)+ = buildAfter (compact $ edge ks v $ afterM e tHole) path++{-# SPECIALIZE extractEdgeLoc :: MonadPlus m => U(Edge) a -> U(Path) a -> m (a, U(EdgeLoc) a) #-}+extractEdgeLoc :: (TrieKey k, MonadPlus m) => Edge v k a -> Path v k a -> m (a, EdgeLoc v k a)+extractEdgeLoc (Edge _ ks v ts) path = case v of+ Nothing -> extractTS+ Just a -> return (a, Loc ks ts path) `mplus` extractTS+ where extractTS = do (e', tHole) <- extractHoleM ts+ extractEdgeLoc e' (Deep path ks v tHole)++{-# SPECIALIZE indexEdge :: Sized a => Int# -> U(Edge) a -> U(Path) a -> (# Int#, a, U(EdgeLoc) a #) #-}+indexEdge :: (TrieKey k, Sized a) => Int# -> Edge v k a -> Path v k a -> (# Int#, a, EdgeLoc v k a #)+indexEdge = indexE where+ indexE i# (Edge _ ks v@(Just a) ts) path+ | i# <# sv# = (# i#, a, Loc ks ts path #)+ | (# i'#, e', tHole #) <- indexM (i# -# sv#) ts+ = indexE i'# e' (Deep path ks v tHole)+ where !sv# = getSize# a+ indexE i# (Edge _ ks Nothing ts) path+ = indexE i'# e' (Deep path ks Nothing tHole)+ where !(# i'#, e', tHole #) = indexM i# ts++{-# SPECIALIZE unifyEdge :: (TrieKey k, Sized a) => V(Slice) -> a -> V(Slice) -> a -> Either (V(EdgeLoc) a) (V(Edge) a) #-}+{-# SPECIALIZE unifyEdge :: Sized a => U(Slice) -> a -> U(Slice) -> a -> Either (U(EdgeLoc) a) (U(Edge) a) #-}+unifyEdge :: (Vector v k, TrieKey k, Sized a) => Slice v k -> a -> Slice v k -> a -> Either (EdgeLoc v k a) (Edge v k a)+unifyEdge ks1 a1 ks2 a2 = iMatchSlice matcher matches ks1 ks2 where+ matcher !i k1 k2 z =+ case unifyM k1 (singletonEdge (dropSlice (i+1) ks1) a1) k2 (singletonEdge (dropSlice (i+1) ks2) a2) of+ Left{} -> z+ Right ts -> Right (edge (takeSlice i ks1) Nothing ts)+ matches len1 len2 = case compare len1 len2 of+ LT -> let (_,k2,ks2') = splitSlice len1 ks2 in+ Right (edge ks1 (Just a1) (singletonM k2 (singletonEdge ks2' a2)))+ GT -> let (_,k1,ks1') = splitSlice len2 ks1 in + Right (edge ks2 (Just a2) (singletonM k1 (singletonEdge ks1' a1)))+ _ -> Left (singleLoc ks1)
+ Data/TrieMap/RadixTrie/Slice.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE BangPatterns #-}+{-# OPTIONS -funbox-strict-fields #-}+module Data.TrieMap.RadixTrie.Slice where++import Control.Exception (assert)+import Data.Vector.Generic+import qualified Data.Vector as V++import Prelude hiding (length, zip, foldr)++data Slice v a = Slice {sliceSrc :: v a, _sliceIx :: !Int, len :: !Int}++{-# INLINE splitSlice #-}+splitSlice :: Vector v a => Int -> Slice v a -> (Slice v a, a, Slice v a)+splitSlice !i !slice = (takeSlice i slice, slice !$ i, dropSlice (i+1) slice)++takeSlice :: Int -> Slice v a -> Slice v a+takeSlice !n (Slice xs i _) = Slice xs i n++dropSlice :: Int -> Slice v a -> Slice v a+dropSlice !m (Slice xs i n) = assert (n >= m) $ Slice xs (i+m) (n-m)++unDropSlice :: Int -> Slice v a -> Slice v a+unDropSlice !m (Slice xs i n) = assert (i >= m) $ Slice xs (i-m) (n+m)++{-# INLINE s2V #-}+s2V :: Vector v a => Slice v a -> v a+s2V (Slice xs i n) = assert (i >= 0) $ assert (i + n < length xs) $ unsafeSlice i n xs++{-# INLINE v2S #-}+v2S :: Vector v a => v a -> Slice v a+v2S xs = Slice xs 0 (length xs)++{-# INLINE matchSliceV #-}+matchSliceV :: (Vector v a, Vector v b) => (a -> b -> z -> z) -> (Int -> Int -> z) -> v a -> Slice v b -> z+matchSliceV f z !xs !ys = foldr (\ (a, b) -> f a b) (z (length xs) (len ys)) (V.zip (convert xs) (convert $ s2V ys))++{-# INLINE matchSlice #-}+matchSlice :: (Vector v a, Vector v b) => (a -> b -> z -> z) -> (Int -> Int -> z) -> Slice v a -> Slice v b -> z+matchSlice f z !xs !ys = foldr (\ (a, b) -> f a b) (z (len xs) (len ys)) (V.zip (convert $ s2V xs) (convert $ s2V ys))++{-# INLINE iMatchSlice #-}+iMatchSlice :: (Vector v a, Vector v b) => (Int -> a -> b -> z -> z) -> (Int -> Int -> z) -> Slice v a -> Slice v b -> z+iMatchSlice f z !xs !ys = ifoldr (\ i (a, b) -> f i a b) (z (len xs) (len ys)) (V.zip (convert $ s2V xs) (convert $ s2V ys))++{-# INLINE (!$) #-}+(!$) :: Vector v a => Slice v a -> Int -> a+Slice xs i n !$ j = assert (j >= 0 && j < n) $ unsafeIndex xs (i + j)
− Data/TrieMap/Rep.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE UndecidableInstances, FlexibleContexts, TypeFamilies, KindSignatures #-}--module Data.TrieMap.Rep where--class Repr a where- type Rep a- toRep :: a -> Rep a- fromRep :: Rep a -> a--class Functor (RepT f) => ReprT f where- type RepT f :: * -> *- toRepT :: f a -> RepT f a- fromRepT :: RepT f a -> f a- toRepTMap :: (a -> b) -> f a -> RepT f b- fromRepTMap :: (b -> a) -> RepT f b -> f a-- toRepT = toRepTMap id- fromRepT = fromRepTMap id- toRepTMap f = fmap f . toRepT- fromRepTMap f = fromRepT . fmap f--{-# RULES- "toRep/fromRep" forall x . toRep (fromRep x) = x;--- "fromRep/toRep" forall x . fromRep (toRep x) = x;- #-}
− Data/TrieMap/Rep/Instances.hs
@@ -1,188 +0,0 @@-{-# LANGUAGE RankNTypes, FlexibleContexts, UndecidableInstances, TypeFamilies, TypeOperators, TemplateHaskell, NPlusKPatterns #-}-{-# OPTIONS -funbox-strict-fields #-}--module Data.TrieMap.Rep.Instances() where--import Data.TrieMap.Rep-import Data.TrieMap.Rep.TH-import Data.TrieMap.Modifiers--import Data.Char-import Data.Int-import Data.Word-import Data.Foldable (toList)-import Data.Bits-import qualified Data.IntSet as ISet-import qualified Data.IntMap as IMap-import Data.ByteString hiding (map)-import qualified Data.ByteString as BS--import Data.Sequence ((|>))-import qualified Data.Sequence as Seq-import qualified Data.Foldable as Fold--import qualified Data.Map as Map-import qualified Data.Set as Set--import Prelude hiding (concat, take, length)--type Pair a = (,) a-type Sum a = Either a--instance ReprT Rev where- type RepT Rev = Rev- toRepTMap = fmap- fromRepTMap = fmap--genRepr [t| Rev |]--instance ReprT [] where- type RepT [] = []- toRepTMap = map- fromRepTMap = map--genRepr [t| [] |]--genTupleRepr 2-genTupleRepr 3-genTupleRepr 4-genTupleRepr 5-genTupleRepr 6-genTupleRepr 7-genTupleRepr 8--instance (Repr a, Repr b) => Repr (Either a b) where- type Rep (Either a b) = Either (Rep a) (Rep b)- toRep (Left a) = Left (toRep a)- toRep (Right b) = Right (toRep b)- fromRep (Left a) = Left (fromRep a)- fromRep (Right b) = Right (fromRep b)--instance Repr Char where- type Rep Char = Word32- toRep = fromIntegral . ord- fromRep = chr . fromIntegral--instance Repr () where- type Rep () = ()- toRep _ = ()- fromRep _ = ()--instance Repr Int where- type Rep Int = Rep Int32- toRep = toSigned- fromRep = fromSigned--instance Repr Word8 where- type Rep Word8 = Word32- toRep = fromIntegral- fromRep = fromIntegral--instance Repr Word16 where- type Rep Word16 = Word32- toRep = fromIntegral- fromRep = fromIntegral--instance Repr Word where- type Rep Word = Word32- toRep = fromIntegral- fromRep = fromIntegral--instance Repr Int8 where- type Rep Int8 = Rep Int32- toRep = toSigned- fromRep = fromSigned--instance Repr Int16 where- type Rep Int16 = Rep Int32- toRep = toSigned- fromRep = fromSigned--instance Repr Int32 where- type Rep Int32 = Sum (Rev Word32) Word32- toRep = toSigned- fromRep = fromSigned--instance Repr Word64 where- type Rep Word64 = Pair Word32 Word32- toRep x = (fromIntegral (x `shiftR` 32), fromIntegral x)- fromRep (x, y) = fromIntegral x `shiftL` 32 .|. fromIntegral y--instance Repr Int64 where- type Rep Int64 = Sum (Rev (Rep Word64)) (Rep Word64)- toRep x | x < 0 = Left (Rev (toRep' (fromIntegral (-x))))- | otherwise = Right (toRep' (fromIntegral x))- where toRep' = toRep :: Word64 -> Rep Word64- fromRep (Left (Rev x)) = - fromIntegral ((fromRep :: Rep Word64 -> Word64) x)- fromRep (Right x) = fromIntegral ((fromRep :: Rep Word64 -> Word64) x)--{-# INLINE toSigned #-}-toSigned :: Integral a => a -> Sum (Rev Word32) Word32-toSigned x- | x < 0 = Left (Rev (fromIntegral (-x)))- | otherwise = Right (fromIntegral x)--{-# INLINE fromSigned #-}-fromSigned :: Integral a => Sum (Rev Word32) Word32 -> a-fromSigned = either (\ (Rev x) -> - fromIntegral x) fromIntegral--instance Repr Word32 where- type Rep Word32 = Word32- toRep = id- fromRep = id--instance Repr ByteString where- type Rep ByteString = ([Word32], Word32)- toRep xs = (toList64 xs, fromIntegral (length xs))- fromRep (xs, n) = case xs of- [] -> BS.empty- (x:xs) -> fst (unfoldrN (fromIntegral n) toBlock (W (Words 3 x) xs))--data Words = Words !Int !Word32-data Words' = W !Words [Word32]--toList64 :: ByteString -> [Word32]-toList64 xs = case BS.foldl' c (Words 4 0, Seq.empty) xs of- (Words _ w32, ys) -> toList ys ++ [w32]- where (Words 0 w, xs) `c` w8- = (Words 3 (w .|. sL w8 24), xs |> w)- (Words i' w, xs) `c` w8- = let !i = i' - 1 in (Words i (w .|. sL w8 (8 * i)), xs)- sL :: Word8 -> Int -> Word32- w `sL` x = fromIntegral w `shiftL` x--toBlock :: Words' -> Maybe (Word8, Words')-toBlock (W (Words i0@(i+1) w) xs) = Just (extract w (8 * i0), (W (Words i w) xs))- where extract :: Word32 -> Int -> Word8- extract w x = fromIntegral (w `shiftR` x)-toBlock (W (Words 0 w) (x:xs)) = Just (fromIntegral w, (W (Words 3 x) xs))-toBlock _ = Nothing--instance ReprT Set.Set where- type RepT Set.Set = []- toRepTMap f s = Fold.foldr ((:) . f) [] s- fromRepTMap f xs = Set.fromDistinctAscList [f x | x <- xs] --genRepr [t| Set.Set |]--instance (Repr k, Repr a) => Repr (Map.Map k a) where- type Rep (Map.Map k a) = [(Rep k, Rep a)]- toRep m = [(toRep k, toRep a) | (k, a) <- Map.assocs m]- fromRep xs = Map.fromDistinctAscList [(fromRep k, fromRep a) | (k, a) <- xs]--instance Repr ISet.IntSet where- type Rep ISet.IntSet = Rep [Int]- toRep = toRep . ISet.toList- fromRep = ISet.fromDistinctAscList . fromRep--instance Repr a => Repr (IMap.IntMap a) where- type Rep (IMap.IntMap a) = [(Rep Int, Rep a)]- toRep m = [(toRep i, toRep a) | (i, a) <- IMap.assocs m]- fromRep xs = IMap.fromDistinctAscList [(fromRep i, fromRep a) | (i, a) <- xs]--instance ReprT Seq.Seq where- type RepT Seq.Seq = []- toRepTMap f = Fold.foldr (\ a xs -> f a:xs) []- fromRepTMap f = Fold.foldl (\ xs a -> xs |> f a) Seq.empty--genRepr [t| Seq.Seq |]
− Data/TrieMap/Rep/TH.hs
@@ -1,38 +0,0 @@-{-# LANGUAGE TypeFamilies, FlexibleContexts, FlexibleInstances, TemplateHaskell, QuasiQuotes, UndecidableInstances #-}--module Data.TrieMap.Rep.TH where--import Language.Haskell.TH-import Data.TrieMap.Rep--genRepr :: Q Type -> Q [Dec]-genRepr typ = do- t <- typ- let a = VarT (mkName "a")- toRepImpl <- [| toRepTMap toRep |]- fromRepImpl <- [| fromRepTMap fromRep |]- return [InstanceD [ClassP ''Repr [a]]- (ConT ''Repr `AppT` (t `AppT` a))- [TySynInstD ''Rep [t `AppT` a] ((ConT ''RepT `AppT` t) `AppT` (ConT ''Rep `AppT` a)),- ValD (VarP 'toRep)- (NormalB toRepImpl) [],- ValD (VarP 'fromRep)- (NormalB fromRepImpl) []]]--genTupleRepr :: Int -> Q [Dec]-genTupleRepr n = do- let ts = [mkName [a] | a <- take n ['a'..]]- xs <- sequence [newName [a] | a <- take n ['a'..]]- xReps <- sequence [newName (a:"Rep") | a <- take n ['a'..]]- let toR = 'toRep- let fromR = 'fromRep- let tupleT = foldl AppT (TupleT n) [VarT t | t <- ts]- return [InstanceD [ClassP ''Repr [VarT t] | t <- ts]- (ConT ''Repr `AppT` tupleT)- [TySynInstD ''Rep [tupleT] (foldl AppT (TupleT n) [ConT ''Rep `AppT` VarT t | t <- ts]),- FunD toR- [Clause [TupP [VarP x | x <- xs]]- (NormalB (TupE [VarE toR `AppE` VarE x | x <- xs])) []],- FunD fromR- [Clause [TupP [VarP xRep | xRep <- xReps]]- (NormalB (TupE [VarE fromR `AppE` VarE xRep | xRep <- xReps])) []]]]
Data/TrieMap/Representation.hs view
@@ -1,42 +1,5 @@-{-# LANGUAGE TypeFamilies, TemplateHaskell, UndecidableInstances #-}-module Data.TrieMap.Representation (Repr(..)) where+module Data.TrieMap.Representation (Repr(..), genRepr, genOptRepr, genOrdRepr) where -import Data.TrieMap.Sized-import Data.TrieMap.TrieKey-import Data.TrieMap.Class-import Data.TrieMap.Rep-import Data.TrieMap.Rep.Instances ()+import Data.TrieMap.Representation.Class+import Data.TrieMap.Representation.Instances () import Data.TrieMap.Representation.TH--import Data.Complex-import Data.Tree-import Data.Ratio-import Foreign.C.Types--instance (TKey k, Repr a) => Repr (TMap k a) where- type Rep (TMap k a) = [(Rep k, Rep a)]- toRep (TMap m) = foldrWithKeyM (\ k (Elem a) xs -> (k, toRep a):xs) m []- fromRep xs = TMap (fromDistAscListM [(k, Elem (fromRep a)) | (k, a) <- xs])--genOrdRepr ''Float-genOrdRepr ''Double-genRepr ''Bool-genRepr ''Tree-genRepr ''Ratio-genRepr ''Maybe-genRepr ''Complex-genRepr ''CInt-genRepr ''CChar-genRepr ''CSChar-genRepr ''CUChar-genRepr ''CShort-genRepr ''CUShort-genRepr ''CUInt-genRepr ''CLong-genRepr ''CULong-genRepr ''CLLong-genRepr ''CULLong-genRepr ''CClock-genRepr ''CTime-genRepr ''CFloat-genRepr ''CDouble
+ Data/TrieMap/Representation/Class.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE TypeFamilies #-}+module Data.TrieMap.Representation.Class where++-- | The @Repr@ type class denotes that a type can be decomposed to a representation+-- built out of pieces for which the 'TrieKey' class defines a generalized trie structure.+-- +-- It is required that, if @('Repr' a, 'Eq' a)@, and @x, y :: a@, then @x '==' y@+-- if and only if @'toRep' x '==' 'toRep' y@. It is typically the case that+-- @'compare' x y == 'compare' ('toRep' x) ('toRep' y)@, as well, but this is not+-- strictly required. (It is, however, the case for all instances built into the package.)+-- +-- As an additional note, the 'Key' modifier is used for \"bootstrapping\" 'Repr' instances,+-- allowing a type to be used in its own 'Repr' definition when wrapped in a 'Key' modifier.+class Repr a where+ type Rep a+ toRep :: a -> Rep a
+ Data/TrieMap/Representation/Instances.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE TemplateHaskell, QuasiQuotes, TypeFamilies, FlexibleInstances #-}+module Data.TrieMap.Representation.Instances () where++import Data.Tree+import Data.Ratio+import Data.Word+import Data.Bits+import Data.TrieMap.Modifiers+import qualified Data.Vector as V+import qualified Data.Vector.Storable as S+import qualified Data.Set as S+import qualified Data.Map as M+import qualified Data.Sequence as Seq++import Data.TrieMap.Utils+import Data.TrieMap.Representation.Class+import Data.TrieMap.Representation.Instances.Prim ()+import Data.TrieMap.Representation.Instances.Basic ()+import Data.TrieMap.Representation.Instances.ByteString ()+import Data.TrieMap.Representation.Instances.Vectors ()+import Data.TrieMap.Representation.Instances.Foreign ()+import Data.TrieMap.Representation.TH++instance Repr a => Repr (S.Set a) where+ type Rep (S.Set a) = V.Vector (Rep a)+ toRep s = toVectorN (\ f -> S.fold (f . toRep)) S.size s++instance (Repr k, Repr a) => Repr (M.Map k a) where+ type Rep (M.Map k a) = V.Vector (Rep k, Rep a)+ toRep m = toVectorN (\ f -> M.foldrWithKey (\ k a -> f (toRep k, toRep a)))+ M.size m++instance Repr a => Repr (Seq.Seq a) where+ type Rep (Seq.Seq a) = V.Vector (Rep a)+ toRep = toVectorF toRep Seq.length++genRepr ''Tree+genRepr ''Ratio++instance Repr Integer where+ type Rep Integer = Either (Rev (Word, S.Vector Word)) (Word, S.Vector Word)+ toRep x+ | x < 0 = let bs = unroll (-x); n = fromIntegral (S.length bs) in Left (Rev (n, bs))+ | otherwise = let bs = unroll x; n = fromIntegral (S.length bs) in Right (n, bs)++unroll :: Integer -> S.Vector Word+unroll x = S.reverse (S.unfoldr split x)+ where wSize = bitSize (0 :: Word)+ split 0 = Nothing+ split x = Just (fromIntegral x :: Word, shiftR x wSize)
+ Data/TrieMap/Representation/Instances/Basic.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE TemplateHaskell, TypeFamilies #-}+module Data.TrieMap.Representation.Instances.Basic () where++import Data.TrieMap.Representation.Class+import Data.TrieMap.Representation.TH++import Control.Monad++import qualified Data.Vector as V++import Language.Haskell.TH++instance Repr a => Repr [a] where+ type Rep [a] = V.Vector (Rep a)+ toRep = V.map toRep . V.fromList++$(let genTupleRepr n = do+ let ts = [mkName [a] | a <- take n ['a'..]]+ xs <- sequence [newName [a] | a <- take n ['a'..]]+ let toR = 'toRep+ let tupleT = foldl AppT (TupleT n) [VarT t | t <- ts]+ return [InstanceD [ClassP ''Repr [VarT t] | t <- ts]+ (ConT ''Repr `AppT` tupleT)+ [TySynInstD ''Rep [tupleT] (foldl AppT (TupleT n) [ConT ''Rep `AppT` VarT t | t <- ts]),+ FunD toR+ [Clause [TupP [VarP x | x <- xs]]+ (NormalB (TupE [VarE toR `AppE` VarE x | x <- xs])) []] {-,+ FunD fromR+ [Clause [TupP [VarP xRep | xRep <- xReps]]+ (NormalB (TupE [VarE fromR `AppE` VarE xRep | xRep <- xReps])) []] -}]]+ in liftM concat $ mapM genTupleRepr [2..10])++genOrdRepr ''Float+genOrdRepr ''Double+genRepr ''Maybe+genRepr ''Either+genRepr ''Bool+genRepr ''()+genRepr ''Ordering
+ Data/TrieMap/Representation/Instances/ByteString.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE UndecidableInstances, TypeFamilies #-}+module Data.TrieMap.Representation.Instances.ByteString () where++import Data.TrieMap.Representation.Class+import Data.TrieMap.Representation.Instances.Vectors ()++import Data.Word++import Data.ByteString.Internal (ByteString(..))+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as L++import Data.Vector.Storable++instance Repr ByteString where+ type Rep ByteString = (Vector Word, Word)+ toRep (PS fp off len) = toRep (unsafeFromForeignPtr fp off len)++instance Repr L.ByteString where+ type Rep L.ByteString = (Vector Word, Word)+ toRep = toRep . B.concat . L.toChunks
+ Data/TrieMap/Representation/Instances/Foreign.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE TemplateHaskell, TypeFamilies, UndecidableInstances #-}+module Data.TrieMap.Representation.Instances.Foreign () where++import Foreign.C.Types+import Data.TrieMap.Representation.Instances.Prim ()+import Data.TrieMap.Representation.Instances.Basic ()+import Data.TrieMap.Representation.TH++genRepr ''CChar+genRepr ''CSChar+genRepr ''CUChar+genRepr ''CShort+genRepr ''CUShort+genRepr ''CInt+genRepr ''CUInt+genRepr ''CLong+genRepr ''CULong+genRepr ''CPtrdiff+genRepr ''CSize+genRepr ''CWchar+genRepr ''CSigAtomic+genRepr ''CLLong+genRepr ''CULLong+genRepr ''CClock+genRepr ''CTime+genRepr ''CFloat+genRepr ''CDouble
+ Data/TrieMap/Representation/Instances/Prim.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE ScopedTypeVariables, BangPatterns, TypeFamilies, UndecidableInstances, CPP #-}+module Data.TrieMap.Representation.Instances.Prim (i2w) where++#include "MachDeps.h"++import Data.TrieMap.Representation.Class+import Data.Word+import Data.Int+import Data.Char+import Data.Bits++instance Repr Char where+ type Rep Char = Word+ toRep = fromIntegral . ord++#define WREPR(wTy) \+instance Repr wTy where { \+ type Rep wTy = Word; \+ toRep = fromIntegral}++WREPR(Word)+WREPR(Word8)+WREPR(Word16)+WREPR(Word32)++#if WORD_SIZE_IN_BITS < 64+instance Repr Word64 where+ type Rep Word64 = (Rep Word32, Rep Word32)+ toRep w = (toRep pre, toRep suf)+ where pre = fromIntegral (w `shiftR` 32) :: Word32+ suf = fromIntegral w :: Word32+#else+WREPR(Word64)+#endif++-- | We embed IntN into WordN, but we have to be careful about overflow.+{-# INLINE [1] i2w #-}+i2w :: forall i w . (Integral i, Bits w, Bits i, Integral w) => i -> w+i2w !i | i < 0 = mB - fromIntegral (-i)+ | otherwise = mB + fromIntegral i+ where mB = bit (bitSize (0 :: i) - 1) :: w++#define IREPR(iTy,wTy) \+instance Repr iTy where { \+ type Rep iTy = Rep wTy; \+ toRep = toRep . (i2w :: iTy -> wTy)}++IREPR(Int8,Word8)+IREPR(Int16,Word16)+IREPR(Int32,Word32)+IREPR(Int64,Word64)+IREPR(Int,Word)
+ Data/TrieMap/Representation/Instances/Vectors.hs view
@@ -0,0 +1,130 @@+{-# LANGUAGE TypeFamilies, FlexibleInstances, CPP, BangPatterns, UndecidableInstances, TemplateHaskell #-}+module Data.TrieMap.Representation.Instances.Vectors () where++import Control.Monad.Primitive++import Data.Word+import Data.Int+import Data.Bits++import Foreign.Storable (Storable)+import Foreign.Ptr+import Foreign.ForeignPtr++import Data.Vector.Generic (convert)+import qualified Data.Vector.Generic as G+import qualified Data.Vector as V+import qualified Data.Vector.Storable as S+import qualified Data.Vector.Primitive as P+import qualified Data.Vector.Unboxed as U++import Data.TrieMap.Representation.Class+import Data.TrieMap.Representation.Instances.Prim++import Language.Haskell.TH.Syntax++#include "MachDeps.h"++instance Repr a => Repr (V.Vector a) where+ type Rep (V.Vector a) = V.Vector (Rep a)+ toRep = V.map toRep++instance Repr (S.Vector Word) where+ type Rep (S.Vector Word) = S.Vector Word+ toRep = id++type Overhang = Word+-- When storing a vector of WordNs, we view it as a vector of Words plus an overhang.+-- We store the length of the overhang (which can be up to (WORD_SIZE_IN_BITS / N - 1)) in the top+-- N bits of the Overhang, and k leftover WordNs (however large k is) in the low kN bits of the Overhang.++-- Just a version of 'quot' for dividing by powers of 2.+quoPow :: Int -> Int -> Int+quoPow n d = $(foldr ($) [| n `quot` d |] + [\ other -> [| if d == $(lift (bit i :: Int)) then n `shiftR` $(lift i) else $other |]+ | i <- [0..6]])++-- Just a version of 'rem' for modding by powers of 2.+remPow :: Int -> Int -> Int+remPow n d = n .&. (d - 1)++unsafeToPtr :: Storable a => S.Vector a -> (Ptr a, Int, ForeignPtr a)+unsafeToPtr xs = unsafeInlineST $ do+ S.MVector ptr n fp <- S.unsafeThaw xs+ return (ptr, n, fp)++unsafeFromPtr :: Storable a => Ptr b -> Int -> ForeignPtr b -> S.Vector a+unsafeFromPtr ptr n fp = unsafeInlineST $ S.unsafeFreeze (S.MVector (castPtr ptr) n (castForeignPtr fp))++#define HANGINSTANCE(wTy) \+ instance Repr (S.Vector wTy) where \+ type Rep (S.Vector wTy) = (S.Vector Word, Overhang); \+ {-# NOINLINE toRep #-}; \+ toRep !xs0 = let { \+ !b = bitSize (0 :: wTy); \+ !wordSize = bitSize (0 :: Word); \+ !ratio = quoPow wordSize b; \+ !n' = quoPow n0 ratio; \+ !nHang = remPow n0 ratio; \+ !xHang = S.drop (n0 - nHang) xs0; \+ !overhang = (fromIntegral nHang `shiftL` (wordSize - b)) .|. \+ S.foldl' (\ hang w -> (hang `shiftL` b) .|. fromIntegral w) 0 xHang; \+ !(ptr, !n0, fp) = unsafeToPtr xs0} \+ in (unsafeFromPtr ptr n' fp, overhang)++HANGINSTANCE(Word8)+HANGINSTANCE(Word16)+#if WORD_SIZE_IN_BITS == 32+instance Repr (S.Vector Word32) where+ type Rep (S.Vector Word32) = S.Vector Word+ toRep xs = case unsafeToPtr xs of+ (p, n, fp) -> unsafeFromPtr p n fp+#elif WORD_SIZE_IN_BITS > 32+HANGINSTANCE(Word32)+#endif++instance Repr (S.Vector Word64) where+ type Rep (S.Vector Word64) = S.Vector Word+ toRep xs = case unsafeToPtr xs of+ (p, n, fp) -> unsafeFromPtr p (n * ratio) fp+ where !wordBits = bitSize (0 :: Word); ratio = quoPow 64 wordBits++#define VEC_WORD_INST(vec,wTy) \+ instance Repr (vec wTy) where { \+ type Rep (vec wTy) = Rep (S.Vector wTy); \+ toRep = (toRep :: S.Vector wTy -> Rep (S.Vector wTy)) . convert}+#define VEC_WORD_INSTANCES(wTy) \+ VEC_WORD_INST(U.Vector,wTy); \+ VEC_WORD_INST(P.Vector,wTy)++VEC_WORD_INSTANCES(Word8)+VEC_WORD_INSTANCES(Word16)+VEC_WORD_INSTANCES(Word32)+VEC_WORD_INSTANCES(Word64)+VEC_WORD_INSTANCES(Word)++#define VEC_INT_INST(vec,iTy,wTy) \+ instance Repr (vec iTy) where { \+ type Rep (vec iTy) = Rep (S.Vector wTy); \+ toRep = (toRep :: S.Vector wTy -> Rep (S.Vector wTy)) . convert . G.map (i2w :: iTy -> wTy)}+#define VEC_INT_INSTANCES(iTy,wTy) \+ VEC_INT_INST(S.Vector,iTy,wTy); \+ VEC_INT_INST(P.Vector,iTy,wTy); \+ VEC_INT_INST(U.Vector,iTy,wTy)++VEC_INT_INSTANCES(Int8, Word8)+VEC_INT_INSTANCES(Int16, Word16)+VEC_INT_INSTANCES(Int32, Word32)+VEC_INT_INSTANCES(Int64, Word64)+VEC_INT_INSTANCES(Int, Word)++#define VEC_ENUM_INST(ty, vec) \+ instance Repr (vec ty) where { \+ type Rep (vec ty) = S.Vector Word; \+ toRep = convert . G.map (fromIntegral . fromEnum)}+#define VEC_ENUM_INSTANCES(ty) \+ VEC_ENUM_INST(ty,S.Vector); \+ VEC_ENUM_INST(ty,P.Vector); \+ VEC_ENUM_INST(ty,U.Vector)++VEC_ENUM_INSTANCES(Char)
Data/TrieMap/Representation/TH.hs view
@@ -1,160 +1,133 @@-{-# LANGUAGE TemplateHaskell, QuasiQuotes, PatternGuards, DoAndIfThenElse #-}+{-# LANGUAGE BangPatterns, TypeFamilies, TemplateHaskell, PatternGuards, DoAndIfThenElse, ImplicitParams #-} -module Data.TrieMap.Representation.TH (genRepr, genOrdRepr) where+module Data.TrieMap.Representation.TH (genRepr, genOptRepr, genOrdRepr) where -import Data.TrieMap.Modifiers-import Data.TrieMap.Rep-import Data.TrieMap.Rep.Instances ()-import Language.Haskell.TH+import Language.Haskell.TH.Syntax import Language.Haskell.TH.ExpandSyns -data ToRepCase = ToRepCase [Pat] Exp-data FromRepCase = FromRepCase Pat [Exp]-type ToRep = [ToRepCase]-type FromRep = [FromRepCase]+import qualified Data.Vector as V -type Representation = (Type, ToRep, FromRep)+import Data.TrieMap.Representation.Class+import Data.TrieMap.Representation.TH.Utils+import Data.TrieMap.Representation.TH.Representation+import Data.TrieMap.Representation.TH.Factorized+import Data.TrieMap.Representation.TH.ReprMonad -- | Given a type with an associated 'Ord' instance, generates a representation that will cause its 'TMap' -- implementation to be essentially equivalent to "Data.Map". genOrdRepr :: Name -> Q [Dec]-genOrdRepr tycon = do- TyConI dec <- reify tycon- let theTyp = foldl AppT (ConT tycon) . map tyVarBndrType+genOrdRepr tycon = execReprMonad $ do+ (cxt, ty, _) <- getDataForName tycon+ outputRepr cxt ty =<< ordRepr ty++getDataForName :: Quasi m => Name -> m (Cxt, Type, [AlgCon])+getDataForName tycon = do+ TyConI dec <- qReify tycon+ let theTyp = compose tycon . map tyVarBndrVar case dec of- DataD cxt _ tyvars _ _ -> do- repr <- ordRepr (theTyp tyvars)- return (decsForRepr cxt (theTyp tyvars) repr)- NewtypeD cxt _ tyvars _ _ -> do- repr <- ordRepr (theTyp tyvars)- return (decsForRepr cxt (theTyp tyvars) repr)- _ -> fail ("Cannot generate Repr instance for " ++ pprint dec)+ DataD cxt _ tyvars cons _ ->+ return (cxt, theTyp tyvars, map algCon cons)+ NewtypeD cxt _ tyvars con _ ->+ return (cxt, theTyp tyvars, [algCon con])+ _ -> error "Error: could not get kind of type constructor" -ordRepr :: Type -> Q Representation-ordRepr t0 = do- x <- newName "x"- return (ConT ''Ordered `AppT` t0, - [ToRepCase [VarP x] (ConE 'Ord `AppE` VarE x)],- [FromRepCase (ConP 'Ord [VarP x])- [VarE x]])- +getDataForType :: Quasi m => Type -> m (Cxt, [AlgCon])+getDataForType ty+ | (ConT tyCon, args) <- decompose ty+ = do TyConI dec <- qReify tyCon+ let subAll tyvars cxt cons = let subs = zip (map tyVarBndrVar tyvars) args in+ ([foldr substInPred p subs | p <- cxt], [foldr substInAlgCon (algCon con) subs | con <- cons])+ case dec of+ DataD cxt _ tyvars cons _ ->+ return (subAll tyvars cxt cons)+ NewtypeD cxt _ tyvars con _ ->+ return (subAll tyvars cxt [con])+ _ -> failure+ | otherwise = failure+ where failure = fail "Error: could not reify type constructor" -- | Given the name of a type constructor, automatically generates an efficient 'Repr' instance.+-- If you have several mutually dependent (or even mutually recursive) types, 'genRepr' will+-- construct instances for all of them. +-- +-- 'genRepr' guarantees that any instances it generates are consistent with the ordering that+-- would be generated by @deriving ('Ord')@ in the data declaration. That is, if 'genRepr'+-- generates an instance @Repr a@, then it is guaranteed that if @x, y :: a@, and @a@+-- has a derived 'Ord' instance, then @compare x y == compare (toRep x) (toRep y)@. genRepr :: Name -> Q [Dec]-genRepr tycon = do- TyConI dec <- reify tycon- let theTyp = foldl AppT (ConT tycon) . map tyVarBndrType- case dec of- DataD cxt _ tyvars cons _ -> do- conReprs <- mapM conRepr cons- return (decsForRepr cxt (theTyp tyvars) (foldr1 union conReprs))- NewtypeD cxt _ tyvars con _ -> do- theConRepr <- conRepr con- return (decsForRepr cxt (theTyp tyvars) theConRepr)- _ -> fail ("Cannot generate Repr instance for " ++ pprint dec)+genRepr tyCon = execReprMonad $ do+ (_, ty, _) <- getDataForName tyCon+ let ?combine = mergeWith sumRepr+ genReprMain ty -tyVarBndrType :: TyVarBndr -> Type-tyVarBndrType (PlainTV tyvar) = VarT tyvar-tyVarBndrType (KindedTV tyvar _) = VarT tyvar+-- | Given the name of a type constructor, automatically generates an efficient 'Repr' instance.+-- If you have several mutually dependent (or even mutually recursive) types, 'genOptRepr' will+-- construct instances for all of them. The instance generated by 'genOptRepr' may, in some+-- cases, be more efficient than the instance generated by 'genRepr' -- in particular,+-- arguments common to several constructors may be factored out, reducing the complexity of the+-- associated 'TrieKey' instance, but leaving an ordering inconsistent with 'Ord'.+-- +-- Therefore, 'genOptRepr' guarantees that any instances it generates are consistent with the+-- ordering that would be generated by @deriving ('Eq')@ in the data declaration. That is, if+-- 'genOptRepr' generates an instance @Repr a@, then it is guaranteed that if @x, y :: a@, and+-- @a@ has a derived 'Eq' instance, then @(x == y) == (toRep x == toRep y)@.+genOptRepr :: Name -> Q [Dec]+genOptRepr tyCon = execReprMonad $ do+ (_, ty, _) <- getDataForName tyCon+ let ?combine = unify+ genReprMain ty -decsForRepr :: Cxt -> Type -> Representation -> [Dec]-decsForRepr cxt t (tRep, toR, fromR) = [- InstanceD cxt (ConT ''Repr `AppT` t)- [TySynInstD ''Rep [t] tRep,- FunD 'toRep- [Clause pats (NormalB e) [] | ToRepCase pats e <- toR],- FunD 'fromRep- [Clause [pat] (NormalB e) [] | FromRepCase pat [e] <- fromR]]]+mustBreakTy :: Type -> ReprMonad Bool+mustBreakTy ty = case decompose ty of+ (ConT tyCon, _) -> mustBreak tyCon+ _ -> return False -decompose :: Type -> (Type, [Type])-decompose (tyfun `AppT` ty) = case decompose tyfun of- (tyfun, tys) -> (tyfun, tys ++ [ty])-decompose ty = (ty, [])+recurseTy :: Type -> ReprMonad a -> ReprMonad a+recurseTy ty m = case decompose ty of+ (ConT tyCon, _) -> recurse tyCon m+ _ -> m -type ReprM = Q+genReprMain :: (?combine :: [Representation] -> Representation) => Type -> ReprMonad Type+genReprMain ty = do+ breakTy <- mustBreakTy ty+ if breakTy then fail "Cannot recurse here"+ else do+ knownInst <- getInstance ty+ case knownInst of+ Just known -> return known+ Nothing -> do+ (cxt, cons) <- getDataForType ty+ conReprs <- mapM (recurseTy ty . conRepr) cons+ outputRepr cxt ty (checkEnumRepr $ ?combine conReprs) -conRepr :: Con -> ReprM Representation-conRepr (RecC con args) = conRepr (NormalC con [(strict, typ) | (_, strict, typ) <- args])-conRepr (InfixC t1 con t2) = conRepr (NormalC con [t1, t2])-conRepr (NormalC con []) = return $ conify con unit-conRepr (NormalC con args) = do- argCons <- mapM (typeRepr . snd) args- return (conify con (foldr1 prod argCons))-conRepr con = fail ("Cannot generate representation for existential constructor " ++ pprint con)+conRepr :: (?combine :: [Representation] -> Representation) => AlgCon -> ReprMonad Representation+conRepr (con, []) = return $ conify con unitRepr+conRepr (con, args) = do+ argReprs <- mapM typeRepr args+ return (conify con (foldr1 prodRepr argReprs)) -typeRepr :: Type -> ReprM Representation-typeRepr t00 = expandSyns t00 >>= \ t0 -> case decompose t0 of+typeRepr :: (?combine :: [Representation] -> Representation) => Type -> ReprMonad Representation+typeRepr t00 = liftQuasi (expandSyns t00) >>= \ t0 -> case decompose t0 of (ListT, [t]) -> do- (tRep, toR, fromR) <- typeRepr t- xs <- newName "elems"- x <- newName "el"- xsRep <- newName "elemReps"- xRep <- newName "elemRep"- return (ListT `AppT` tRep,- [ToRepCase [VarP xs] - (CompE [BindS (VarP x) (VarE xs),- NoBindS (CaseE (VarE x) [Match pat (NormalB e) [] | ToRepCase [pat] e <- toR])])],- [FromRepCase (VarP xsRep)- [CompE [BindS (VarP xRep) (VarE xsRep),- NoBindS (CaseE (VarE xRep) [Match pat (NormalB e) [] | FromRepCase pat [e] <- fromR])]]])- (TupleT 0, _) -> return unit+ tRepr <- typeRepr t+ vectorizeRepr (VarE 'V.fromList) tRepr+ (TupleT 0, _) -> return unitRepr (TupleT _, ts) -> do reps <- mapM typeRepr ts- let (tRep, toR, fromR) = foldr1 prod reps- return (tRep, [ToRepCase [TupP pats] e | ToRepCase pats e <- toR], [FromRepCase pat [TupE es] | FromRepCase pat es <- fromR])+ return $ mapReprInput TupP $ mergeWith prodRepr reps (ConT con, ts)- | con == ''() -> return unit+ | con == ''() -> return unitRepr | con == ''Either, [tL, tR] <- ts- -> do (tRepL, lToR, lFromR) <- typeRepr tL- (tRepR, rToR, rFromR) <- typeRepr tR- return (ConT ''Either `AppT` tRepL `AppT` tRepR,- [ToRepCase [ConP 'Left pats] (ConE 'Left `AppE` e) | ToRepCase pats e <- lToR] ++- [ToRepCase [ConP 'Right pats] (ConE 'Right `AppE` e) | ToRepCase pats e <- rToR],- [FromRepCase (ConP 'Left [pat]) [ConE 'Left `AppE` e] | FromRepCase pat [e] <- lFromR] ++- [FromRepCase (ConP 'Right [pat]) [ConE 'Right `AppE` e] | FromRepCase pat [e] <- rFromR])- | otherwise -> do ClassI _ instances <- reify ''Repr- let knowns = [tycon | ClassInstance{ci_tys = [ConT tycon]} <- instances]- -- TODO: recognize preexisting higher-arity instances- if con `elem` knowns && null ts then do- arg <- newName "arg"- argRep <- newName "argRep"- return (ConT ''Rep `AppT` ConT con,- [ToRepCase [VarP arg] (VarE 'toRep `AppE` VarE arg)],- [FromRepCase (VarP argRep) [VarE 'fromRep `AppE` VarE argRep]])- else recursiveRepr t0- _ -> recursiveRepr t0--recursiveRepr :: Type -> ReprM Representation-recursiveRepr t0 = do -- TODO: handle type synonyms here- x <- newName "arg"- return (ConT ''Key `AppT` t0, - [ToRepCase [VarP x] (ConE 'Key `AppE` VarE x)],- [FromRepCase (ConP 'Key [VarP x]) [VarE x]])--unit :: Representation-unit = (TupleT 0, [ToRepCase [] (TupE [])], [FromRepCase WildP []])--prod :: Representation -> Representation -> Representation-prod (t1, toRep1, fromRep1)- (t2, toRep2, fromRep2) =- (TupleT 2 `AppT` t1 `AppT` t2,- do ToRepCase pats1 out1 <- toRep1- ToRepCase pats2 out2 <- toRep2- return (ToRepCase (pats1 ++ pats2) (TupE [out1, out2])),- do FromRepCase pat1 out1 <- fromRep1- FromRepCase pat2 out2 <- fromRep2- return (FromRepCase (TupP [pat1, pat2]) (out1 ++ out2)))--conify :: Name -> Representation -> Representation-conify conName (t, toR, fromR) =- (t, [ToRepCase [ConP conName args] e | ToRepCase args e <- toR], - [FromRepCase p [foldl AppE (ConE conName) outs] | FromRepCase p outs <- fromR])+ -> do reprL <- typeRepr tL+ reprR <- typeRepr tR+ return (mapReprInput (ConP leftN) reprL `sumRepr` mapReprInput (ConP rightN) reprR)+ | con == ''Maybe, [t] <- ts+ -> do tRepr <- typeRepr t+ return (conify 'Nothing unitRepr `sumRepr` conify 'Just tRepr)+ _ -> bootstrapRepr t0 -union :: Representation -> Representation -> Representation-union (t1, toRep1, fromRep1)- (t2, toRep2, fromRep2) =- (ConT ''Either `AppT` t1 `AppT` t2,- [ToRepCase pats (ConE 'Left `AppE` e) | ToRepCase pats e <- toRep1] ++- [ToRepCase pats (ConE 'Right `AppE` e) | ToRepCase pats e <- toRep2],- [FromRepCase (ConP 'Left [pat]) es | FromRepCase pat es <- fromRep1] ++- [FromRepCase (ConP 'Right [pat]) es | FromRepCase pat es <- fromRep2])+bootstrapRepr :: (?combine :: [Representation] -> Representation) => Type -> ReprMonad Representation+bootstrapRepr t0 = qRecover fallback+ (do _tRep <- genReprMain t0+ recursiveRepr (ConT ''Rep `AppT` t0) (VarE 'toRep))+ where fallback = keyRepr t0
+ Data/TrieMap/Representation/TH/Factorized.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE ParallelListComp, NamedFieldPuns, RecordWildCards #-}+module Data.TrieMap.Representation.TH.Factorized (unify) where++import Control.Exception++import Data.List+import Data.Maybe+import Data.Ord++import Language.Haskell.TH+import Data.TrieMap.Representation.TH.Representation+import Data.TrieMap.Representation.TH.Utils++data FactorCase = FCase {fInput :: [Pat], fFactor :: Exp, fOutput :: Exp}+data Factored = Factored {factorType :: Type, fRestType :: Type, fCases :: [FactorCase]}++factorRepr, otherRepr :: Factored -> Representation+factorRepr Factored{..} =+ Repr {reprType = factorType, cases = map factorCase fCases}+otherRepr Factored{..} =+ Repr {reprType = fRestType, cases = map otherCase fCases}++factorCase, otherCase :: FactorCase -> Case+factorCase FCase{..} = Case{input = fInput, output = fFactor}+otherCase FCase{..} = Case{input = fInput, output = fOutput}++caseFactor :: Case -> FactorCase+caseFactor Case{..} = FCase{fInput = input, fFactor = output, fOutput = TupE []}++combFCase :: Case -> FactorCase -> FactorCase+combFCase Case{..} FCase{..} = + assert (input == fInput) $ FCase{fOutput = TupE [output, fOutput], ..}++combFactor :: Representation -> Factored -> Factored+combFactor Repr{..} Factored{fRestType = TupleT 0,..} =+ Factored{factorType, fRestType = reprType, fCases = [FCase{fOutput = output,..} | (FCase{..}, Case{output}) <- zip fCases cases]}+combFactor Repr{..} Factored{..} =+ Factored{factorType, fRestType = reprType `tyProd` fRestType, fCases = zipWith combFCase cases fCases}++factors :: Representation -> [Factored]+factors repr@Repr{..} = case reprType of+ TupleT 2 `AppT` _ `AppT` _+ -> let fs1 = map (combFactor (sndRepr repr)) (factors (fstRepr repr))+ fs2 = map (combFactor (fstRepr repr)) (factors (sndRepr repr))+ in baseFactor:fs1 ++ fs2+ _ -> [baseFactor]+ where baseFactor = Factored {+ factorType = reprType,+ fRestType = TupleT 0,+ fCases = map caseFactor cases}++distinctFactors :: [Representation] -> [Type]+distinctFactors reprs = nub [factorType | repr <- reprs, Factored{factorType} <- factors repr, factorType /= TupleT 0]++factorWith :: Type -> Representation -> Maybe Factored+factorWith fTy repr = listToMaybe [factor | factor@Factored{factorType} <- factors repr, factorType == fTy]++factorOut :: Type -> [Representation] -> ([Factored], [Representation])+factorOut _ [] = ([], [])+factorOut fTy (repr:reprs) = case (factorWith fTy repr, factorOut fTy reprs) of+ (Nothing, (factors, others)) -> (factors, repr:others)+ (Just f, (factors, others)) -> (f:factors, others)++unify :: [Representation] -> Representation+unify reprs = case (allFactors, bestOption) of+ ([], _) -> checkEnumRepr (mergeWith sumRepr reprs)+ (_, ([_], _)) -> checkEnumRepr (mergeWith sumRepr reprs)+ (_, (factors, [])) -> distributeMany factors+ (_, (factors, others)) -> distributeMany factors `sumRepr` unify others+ where allFactors = distinctFactors reprs+ options = map (`factorOut` reprs) (distinctFactors reprs)+ bestOption = maximumBy (comparing (length . fst)) options++distributeMany :: [Factored] -> Representation+distributeMany factors =+ foldr1 unifySumRepr (map factorRepr factors) `unifyProdRepr` unify (map otherRepr factors)
+ Data/TrieMap/Representation/TH/ReprMonad.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE ViewPatterns, TemplateHaskell #-}+module Data.TrieMap.Representation.TH.ReprMonad (+ ReprMonad,+ liftQuasi,+ recurse,+ getInstance,+ outputInstance,+ mustBreak,+ execReprMonad) where++import Data.TrieMap.Representation.Class+import Data.TrieMap.Representation.TH.Utils++import Control.Monad+import Language.Haskell.TH.Syntax+import Language.Haskell.TH.ExpandSyns++type Instances = [(Name, ([Name], Type))]++newtype ReprMonad a = ReprMonad {runReprMonad ::+ Instances -- tycons of known instances+ -> [Name] -- tycons of instances in progress (breakpoints of recursive loopies)+ -> Q ([Dec], Instances, a) -- output decs, new known instances+ }++instance Monad ReprMonad where+ return x = ReprMonad $ \ knowns _ -> return ([], knowns, x)+ m >>= k = ReprMonad $ \ knowns breaks -> do+ (outDecs, knowns', a) <- runReprMonad m knowns breaks+ (outDecs', knowns'', b) <- runReprMonad (k a) knowns' breaks+ return (outDecs ++ outDecs', knowns'', b)+ fail err = ReprMonad $ \ _ _ -> fail err++instance Functor ReprMonad where+ fmap = liftM++liftQuasi :: Q a -> ReprMonad a+liftQuasi q = ReprMonad $ \ knowns _ -> do+ a <- q+ return ([], knowns, a)++instance Quasi ReprMonad where+ qNewName = liftQuasi . qNewName+ qReport b str = liftQuasi (qReport b str)+ qRecover m k = ReprMonad $ \ knowns breaks -> qRecover (runReprMonad m knowns breaks) (runReprMonad k knowns breaks)+ qReify = liftQuasi . qReify+ qClassInstances name typs = liftQuasi (qClassInstances name typs)+ qLocation = liftQuasi qLocation+ qRunIO = liftQuasi . qRunIO++insNub :: Eq a => a -> [a] -> [a]+insNub x ys0@(y:ys)+ | x == y = ys0+ | otherwise = y:insNub x ys+insNub x [] = [x]++recurse :: Name -> ReprMonad a -> ReprMonad a+recurse breakTy m = ReprMonad $ \ knowns breaks -> runReprMonad m knowns (breakTy `insNub` breaks)++outputInstance :: Type -> Type -> [Dec] -> ReprMonad ()+outputInstance ty tyRep decs = ReprMonad $ \ knowns _ -> case decompose' ty of+ Just (tyCon, tyArgs)+ -> return (decs, (tyCon, (tyArgs, tyRep)):knowns, ())+ _ -> return (decs, knowns, ())++getInstance :: Type -> ReprMonad (Maybe Type)+getInstance typ = case decompose typ of+ (ConT tyCon, tyArgs) -> ReprMonad $ \ knowns _ -> case lookup tyCon knowns of+ Nothing -> return ([], knowns, Nothing)+ Just (tyArgs', tyRep) -> return ([], knowns, Just $ foldr substInType tyRep (zip tyArgs' tyArgs))+ _ -> return Nothing++mustBreak :: Name -> ReprMonad Bool+mustBreak tyCon = ReprMonad $ \ knowns breaks -> return ([], knowns, tyCon `elem` breaks)++execReprMonad :: ReprMonad a -> Q [Dec]+execReprMonad m = do+ ClassI _ instances <- reify ''Repr+ let instanceHeads = [(tyConName, (tyArgs, ConT ''Rep `AppT` compose tyConName tyArgs))+ | ClassInstance{ci_tys = [decompose' -> Just (tyConName, tyArgs)]} <- instances]+ (decs, _, _) <- runReprMonad m instanceHeads []+ return decs
+ Data/TrieMap/Representation/TH/Representation.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE TemplateHaskell, RecordWildCards, NamedFieldPuns, PatternGuards #-}+module Data.TrieMap.Representation.TH.Representation (+ Representation(..),+ Case(..),+ fstRepr,+ sndRepr,+ prodRepr,+ sumRepr,+ unifyProdRepr,+ unifySumRepr,+ checkEnumRepr,+ unitRepr,+ vectorizeRepr,+ mapReprInput,+ conify,+ ordRepr,+ outputRepr,+ recursiveRepr,+ keyRepr) where++import Control.Exception (assert)+import Control.Monad++import Data.Word+import Data.Maybe+import qualified Data.Vector as V++import Language.Haskell.TH.Syntax++import Data.TrieMap.Modifiers+import Data.TrieMap.Representation.Class+import Data.TrieMap.Representation.TH.Utils+import Data.TrieMap.Representation.TH.ReprMonad++data Representation = Repr {reprType :: Type, cases :: [Case]} deriving (Show)+data Case = Case {input :: [Pat], output :: Exp} deriving (Show)++unitRepr :: Representation+unitRepr = Repr {reprType = TupleT 0, cases = [Case [] (TupE [])]}++vectorizeRepr :: Quasi m => Exp -> Representation -> m Representation+vectorizeRepr toVecE Repr{..} = do+ xs <- qNewName "xs"+ eToR <- qNewName "eToR"+ let mapE f xs = VarE 'V.map `AppE` f `AppE` xs+ let eToRDec = FunD eToR (map caseToClause cases)+ return $ Repr {+ reprType = ConT ''V.Vector `AppT` reprType,+ cases = [Case {input = [VarP xs],+ output = mapE (LetE [eToRDec] (VarE eToR)) (toVecE `AppE` VarE xs)}]}++fstRepr, sndRepr :: Representation -> Representation+fstRepr = mapReprOutput fstTy fstExp+sndRepr = mapReprOutput sndTy sndExp++prodCase :: Case -> Case -> Case+prodCase Case{input = input1, output = output1} Case{input = input2, output = output2}+ = Case {input = input1 ++ input2, output = TupE [output1, output2]}++unifyProdCase :: Case -> Case -> Maybe Case+unifyProdCase Case{input = input1, output = output1} Case{input = input2, output = output2}+ = do guard (input1 == input2)+ return Case{input = input1, output = TupE [output1, output2]}++mapCaseInput :: ([Pat] -> Pat) -> Case -> Case+mapCaseInput f Case{..} = Case{input = [f input],..}++mapCaseOutput :: (Exp -> Exp) -> Case -> Case+mapCaseOutput f Case{..} = Case{output = f output,..}++prodRepr, sumRepr, unifySumRepr, unifyProdRepr :: Representation -> Representation -> Representation+prodRepr Repr{reprType = repr1, cases = cases1} Repr{reprType = repr2, cases = cases2}+ = Repr {reprType = repr1 `tyProd` repr2, cases = liftM2 prodCase cases1 cases2}++sumRepr Repr{reprType = repr1, cases = cases1} Repr{reprType = repr2, cases = cases2}+ = Repr {reprType = repr1 `tySum` repr2, + cases = map (mapCaseOutput leftExp) cases1 ++ map (mapCaseOutput rightExp) cases2}++unifySumRepr Repr{reprType = repr1, cases = cases1} Repr{reprType = repr2, cases = cases2}+ = assert (repr1 == repr2) $ Repr {reprType = repr1, cases = cases1 ++ cases2}++unifyProdRepr Repr{reprType = repr1, cases = cases1} Repr{reprType = repr2, cases = cases2}+ = Repr {reprType = repr1 `tyProd` repr2, cases = catMaybes (liftM2 unifyProdCase cases1 cases2)}++mapReprInput :: ([Pat] -> Pat) -> Representation -> Representation+mapReprInput f Repr{..} = Repr{cases = map (mapCaseInput f) cases, ..}++conify :: Name -> Representation -> Representation+conify con = mapReprInput (ConP con)++mapReprOutput :: (Type -> Type) -> (Exp -> Exp) -> Representation -> Representation+mapReprOutput tyOp outOp Repr{..} = Repr{reprType = tyOp reprType, cases = map (mapCaseOutput outOp) cases}++checkEnumRepr :: Representation -> Representation+checkEnumRepr Repr{..}+ | isEnumTy reprType, length cases > 2+ = Repr {reprType = ConT ''Word, cases = [Case{input, output = LitE (IntegerL i)} | (i, Case{..}) <- zip [0..] cases]}+checkEnumRepr repr = repr++ordRepr :: Quasi m => Type -> m Representation+ordRepr ty = do+ x <- qNewName "ordK"+ return Repr{reprType = ConT ''Ordered `AppT` ty, + cases = [Case {input = [VarP x], output = ConE 'Ord `AppE` VarE x}]}++caseToClause :: Case -> Clause+caseToClause Case{..} = Clause input (NormalB output) []++outputRepr :: Cxt -> Type -> Representation -> ReprMonad Type+outputRepr cxt ty Repr{..} = do+ outputInstance ty reprType+ [InstanceD cxt (ConT ''Repr `AppT` ty)+ [TySynInstD ''Rep [ty] reprType,+ FunD 'toRep+ (map caseToClause cases)]]+ return reprType++recursiveRepr :: Quasi m => Type -> Exp -> m Representation+recursiveRepr reprType toRepE = do+ deep <- qNewName "deep"+ return Repr{reprType, cases = [Case{input = [VarP deep], output = toRepE `AppE` VarE deep}]}++keyRepr :: Quasi m => Type -> m Representation+keyRepr ty = do+ shallow <- qNewName "shallow"+ let keyCon = ConE 'Key+ return Repr{reprType = ConT ''Key `AppT` ty, cases = [Case{input = [VarP shallow], output = keyCon `AppE` VarE shallow}]}
+ Data/TrieMap/Representation/TH/Utils.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE TemplateHaskell #-}+module Data.TrieMap.Representation.TH.Utils where++import Language.Haskell.TH+import Language.Haskell.TH.ExpandSyns++decompose :: Type -> (Type, [Type])+decompose (tyfun `AppT` ty) = case decompose tyfun of+ (tyfun, tys) -> (tyfun, tys ++ [ty])+decompose ty = (ty, [])++decompose' :: Type -> Maybe (Name, [Name])+decompose' (tyfun `AppT` VarT ty) = do+ (tyfun, tys) <- decompose' tyfun+ return (tyfun, tys ++ [ty])+decompose' (ConT ty) = return (ty, [])+decompose' _ = Nothing++compose :: Name -> [Name] -> Type+compose tyCon tyArgs = foldl AppT (ConT tyCon) (map VarT tyArgs)++tyVarBndrVar :: TyVarBndr -> Name+tyVarBndrVar (PlainTV tyvar) = tyvar+tyVarBndrVar (KindedTV tyvar _) = tyvar++tyVarBndrType :: TyVarBndr -> Type+tyVarBndrType = VarT . tyVarBndrVar++tyProd, tySum :: Type -> Type -> Type+tyProd t1 t2 = TupleT 2 `AppT` t1 `AppT` t2+tySum t1 t2 = ConT ''Either `AppT` t1 `AppT` t2++fstExp, sndExp :: Exp -> Exp+fstExp (TupE [e, _]) = e+fstExp e = VarE 'fst `AppE` e+sndExp (TupE [_, e]) = e+sndExp e = VarE 'snd `AppE` e++leftN, rightN :: Name+leftN = 'Left+rightN = 'Right++leftExp, rightExp :: Exp -> Exp+leftExp = AppE (ConE leftN)+rightExp = AppE (ConE rightN)++fstTy, sndTy :: Type -> Type+fstTy (TupleT 2 `AppT` t1 `AppT` _) = t1+fstTy _ = error "Error: not a pair type"+sndTy (TupleT 2 `AppT` _ `AppT` t2) = t2+sndTy _ = error "Error: not a pair type"++isEnumTy :: Type -> Bool+isEnumTy (ConT eith `AppT` t1 `AppT` t2)+ = eith == ''Either && isEnumTy t1 && isEnumTy t2+isEnumTy (TupleT 0)+ = True+isEnumTy _ = False++type AlgCon = (Name, [Type])++algCon :: Con -> AlgCon+algCon (NormalC name args) = (name, map snd args)+algCon (RecC name args) = (name, [argTy | (_, _, argTy) <- args])+algCon (InfixC (_, ty1) name (_, ty2)) = (name, [ty1, ty2])+algCon _ = error "Error: universally quantified constructors are not algebraic"++substInAlgCon :: (Name, Type) -> AlgCon -> AlgCon+substInAlgCon sub (conName, args) = (conName, map (substInType sub) args)++substInPred :: (Name, Type) -> Pred -> Pred+substInPred sub (ClassP cName tys) = ClassP cName (map (substInType sub) tys)+substInPred sub (EqualP ty1 ty2) = EqualP (substInType sub ty1) (substInType sub ty2)++mergeWith :: (a -> a -> a) -> [a] -> a+mergeWith _ [a] = a+mergeWith _ [] = error "Error: mergeWith called with empty list"+mergeWith f xs = mergeWith f (combine xs) where+ combine (x1:x2:xs) = f x1 x2:combine xs+ combine xs = xs
Data/TrieMap/ReverseMap.hs view
@@ -1,58 +1,57 @@-{-# LANGUAGE UnboxedTuples, TypeFamilies, BangPatterns, MagicHash #-}+{-# LANGUAGE TypeFamilies, MagicHash, UnboxedTuples #-}+module Data.TrieMap.ReverseMap () where -module Data.TrieMap.ReverseMap (reverse, unreverse) where+import Control.Applicative +import Data.TrieMap.Applicative import Data.TrieMap.TrieKey-import Data.TrieMap.Sized import Data.TrieMap.Modifiers-import Data.TrieMap.Applicative--import Control.Applicative--import Prelude hiding (reverse)-import qualified Data.List as L+import Data.TrieMap.Sized import GHC.Exts instance TrieKey k => TrieKey (Rev k) where- newtype TrieMap (Rev k) a = RMap (TrieMap k a)+ newtype TrieMap (Rev k) a = RevMap (TrieMap k a) newtype Hole (Rev k) a = RHole (Hole k a)- emptyM = RMap emptyM- singletonM (Rev k) a = RMap (singletonM k a)- nullM (RMap m) = nullM m- sizeM (RMap m) = sizeM m- lookupM (Rev k) (RMap m) = lookupM k m- mapWithKeyM f (RMap m) = RMap (mapWithKeyM (f . Rev) m)- traverseWithKeyM f (RMap m) = RMap <$> runDual (traverseWithKeyM g m)- where g k a = Dual (f (Rev k) a)- mapMaybeM f (RMap m) = RMap (mapMaybeM (f . Rev) m)- mapEitherM f (RMap m) = both RMap RMap (mapEitherM (f . Rev)) m- foldrWithKeyM f (RMap m) = foldlWithKeyM (flip . f . Rev) m- foldlWithKeyM f (RMap m) = foldrWithKeyM (flip . f . Rev) m- unionM f (RMap m1) (RMap m2) = RMap (unionM (f . Rev) m1 m2)- isectM f (RMap m1) (RMap m2) = RMap (isectM (f . Rev) m1 m2)- diffM f (RMap m1) (RMap m2) = RMap (diffM (f . Rev) m1 m2)- isSubmapM (<=) (RMap m1) (RMap m2) = isSubmapM (<=) m1 m2- fromListM f xs = RMap (fromListM (f . Rev) [(k, a) | (Rev k, a) <- xs])- fromAscListM f xs = RMap (fromAscListM (\ k a1 a2 -> f (Rev k) a2 a1) [(k, a) | (Rev k, a) <- L.reverse xs])- fromDistAscListM xs = RMap (fromDistAscListM [(k, a) | (Rev k, a) <- L.reverse xs]) + Rev k1 =? Rev k2 = k1 =? k2+ Rev k1 `cmp` Rev k2 = k2 `cmp` k1+ + emptyM = RevMap emptyM+ singletonM (Rev k) a = RevMap (singletonM k a)+ lookupM (Rev k) (RevMap m) = lookupM k m+ sizeM (RevMap m) = sizeM m+ getSimpleM (RevMap m) = getSimpleM m+ + fmapM f (RevMap m) = RevMap (fmapM f m)+ traverseM f (RevMap m) = RevMap <$> runDual (traverseM (Dual . f) m)+ + foldlM f (RevMap m) = foldrM (flip f) m+ foldrM f (RevMap m) = foldlM (flip f) m+ + mapMaybeM f (RevMap m) = RevMap (mapMaybeM f m)+ mapEitherM f (RevMap m) = both RevMap RevMap (mapEitherM f) m+ unionM f (RevMap m1) (RevMap m2) = RevMap (unionM f m1 m2)+ isectM f (RevMap m1) (RevMap m2) = RevMap (isectM f m1 m2)+ diffM f (RevMap m1) (RevMap m2) = RevMap (diffM f m1 m2)+ isSubmapM (<=) (RevMap m1) (RevMap m2) = isSubmapM (<=) m1 m2+ singleHoleM (Rev k) = RHole (singleHoleM k)- keyM (RHole hole) = Rev (keyM hole)- beforeM a (RHole hole) = RMap (afterM a hole)- afterM a (RHole hole) = RMap (beforeM a hole)- searchM (Rev k) (RMap m) = onUnboxed RHole (searchM k) m- indexM i# (RMap m) = case indexM (sm# -# 1# -# i#) m of- (# i'#, v, hole #) -> (# getSize# v -# 1# -# i'#, v, RHole hole #)- where !sm# = sizeM m- extractHoleM (RMap m) = do- (v, hole) <- runDualPlus (extractHoleM m)- return (v, RHole hole)- assignM x (RHole hole) = RMap (assignM x hole)- clearM (RHole hole) = RMap (clearM hole)--reverse :: TrieMap k a -> TrieMap (Rev k) a-reverse = RMap+ beforeM a (RHole hole) = RevMap (afterM a hole)+ afterM a (RHole hole) = RevMap (beforeM a hole)+ searchM (Rev k) (RevMap m) = onSnd RHole (searchM k) m+ indexM i# (RevMap m) = case indexM (revIndex i# m) m of+ (# i'#, a, hole #) -> (# revIndex i'# a, a, RHole hole #)+ extractHoleM (RevMap m) = runDualPlus $ do+ (a, hole) <- extractHoleM m+ return (a, RHole hole)+ assignM v (RHole m) = RevMap (assignM v m)+ + fromListM f xs = RevMap (fromListM f [(k, a) | (Rev k, a) <- xs])+ fromAscListM f xs = RevMap (fromAscListM (flip f) [(k, a) | (Rev k, a) <- reverse xs])+ fromDistAscListM xs = RevMap (fromDistAscListM [(k, a) | (Rev k, a) <- reverse xs])+ + unifyM (Rev k1) a1 (Rev k2) a2 = either (Left . RHole) (Right . RevMap) (unifyM k1 a1 k2 a2) -unreverse :: TrieMap (Rev k) a -> TrieMap k a-unreverse (RMap m) = m+revIndex :: Sized a => Int# -> a -> Int#+revIndex i# a = getSize# a -# 1# -# i#
Data/TrieMap/Sized.hs view
@@ -7,10 +7,19 @@ class Sized a where getSize# :: a -> Int# -newtype Elem a = Elem {getElem :: a}+data Assoc k a = Assoc {getK :: k, getValue :: a} +newtype Elem a = Elem a+ instance Sized (Elem a) where getSize# _ = 1#++instance Sized (Assoc k a) where+ getSize# _ = 1#++instance Sized a => Sized (Maybe a) where+ getSize# (Just a) = getSize# a+ getSize# _ = 0# getSize :: Sized a => a -> Int getSize a = I# (getSize# a)
− Data/TrieMap/TrieKey.hs
@@ -1,135 +0,0 @@-{-# LANGUAGE TupleSections, TypeFamilies, UnboxedTuples, MagicHash #-}--module Data.TrieMap.TrieKey where--import Data.TrieMap.Sized--import Control.Applicative-import Control.Monad--import Data.Monoid-import Data.Foldable--import Prelude hiding (foldr, foldl)---import GHC.Exts--type EitherMap k a b c = k -> a -> (# Maybe b, Maybe c #)-type SplitMap a x = a -> (# Maybe a, Maybe x, Maybe a #)-type UnionFunc k a = k -> a -> a -> Maybe a-type IsectFunc k a b c = k -> a -> b -> Maybe c-type DiffFunc k a b = k -> a -> b -> Maybe a-type LEq a b = a -> b -> Bool--onUnboxed :: (c -> d) -> (a -> (# b, c #)) -> a -> (# b, d #)-onUnboxed g f a = case f a of- (# b, c #) -> (# b, g c #)--instance TrieKey k => Foldable (TrieMap k) where- foldr f z m = foldrWithKeyM (const f) m z- foldl f z m = foldlWithKeyM (const f) m z--class Ord k => TrieKey k where- data TrieMap k :: * -> *- emptyM :: TrieMap k a- singletonM :: Sized a => k -> a -> TrieMap k a- nullM :: TrieMap k a -> Bool- sizeM :: Sized a => TrieMap k a -> Int#- lookupM :: k -> TrieMap k a -> Maybe a- mapWithKeyM :: Sized b => (k -> a -> b) -> TrieMap k a -> TrieMap k b- traverseWithKeyM :: (Applicative f, Sized b) =>- (k -> a -> f b) -> TrieMap k a -> f (TrieMap k b)- foldrWithKeyM :: (k -> a -> b -> b) -> TrieMap k a -> b -> b- foldlWithKeyM :: (k -> b -> a -> b) -> TrieMap k a -> b -> b- mapMaybeM :: Sized b => (k -> a -> Maybe b) -> TrieMap k a -> TrieMap k b- mapEitherM :: (Sized b, Sized c) => EitherMap k a b c -> TrieMap k a -> (# TrieMap k b, TrieMap k c #)- unionM :: Sized a => UnionFunc k a -> TrieMap k a -> TrieMap k a -> TrieMap k a- isectM :: (Sized a, Sized b, Sized c) => IsectFunc k a b c -> TrieMap k a -> TrieMap k b -> TrieMap k c- diffM :: Sized a => DiffFunc k a b -> TrieMap k a -> TrieMap k b -> TrieMap k a- isSubmapM :: (Sized a, Sized b) => LEq a b -> LEq (TrieMap k a) (TrieMap k b)- fromListM, fromAscListM :: Sized a => (k -> a -> a -> a) -> [(k, a)] -> TrieMap k a- fromDistAscListM :: Sized a => [(k, a)] -> TrieMap k a- - data Hole k :: * -> *- singleHoleM :: k -> Hole k a- keyM :: Hole k a -> k- beforeM :: Sized a => Maybe a -> Hole k a -> TrieMap k a- afterM :: Sized a => Maybe a -> Hole k a -> TrieMap k a- searchM :: k -> TrieMap k a -> (# Maybe a, Hole k a #)- indexM :: Sized a => Int# -> TrieMap k a -> (# Int#, a, Hole k a #)- {-# SPECIALIZE extractHoleM :: Sized a => TrieMap k a -> First (a, Hole k a) #-}- {-# SPECIALIZE extractHoleM :: Sized a => TrieMap k a -> Last (a, Hole k a) #-}- extractHoleM :: MonadPlus m => Sized a => TrieMap k a -> m (a, Hole k a)- assignM :: Sized a => a -> Hole k a -> TrieMap k a- clearM :: Sized a => Hole k a -> TrieMap k a-- singletonM k a = assignM a (singleHoleM k)- lookupM k m = case searchM k m of- (# a, _ #) -> a- foldrWithKeyM f = appEndo . getConst . traverseWithKeyM (endofy f) where- endofy :: (k -> a -> b -> b) -> k -> a -> Const (Endo b) (Elem ())- endofy f k a = Const (Endo (f k a))- foldlWithKeyM f m = foldrWithKeyM (\ k a g z -> g (f k z a)) m id- fromListM f = foldr (uncurry (insertWithKeyM f)) emptyM- fromAscListM = fromListM- fromDistAscListM = fromAscListM (const const)--instance (TrieKey k, Sized a) => Sized (TrieMap k a) where- getSize# = sizeM--{-# INLINE alterM #-}-alterM :: (TrieKey k, Sized a) => (Maybe a -> Maybe a) -> k -> TrieMap k a -> TrieMap k a-alterM f k m = case searchM k m of- (# Nothing, hole #) -> maybe m (\ a -> assignM a hole) (f Nothing)- (# a, hole #) -> fillHoleM (f a) hole--traverseM :: (Applicative f, TrieKey k, Sized b) => (a -> f b) -> TrieMap k a -> f (TrieMap k b)-traverseM f = traverseWithKeyM (const f)--guardNullM :: TrieKey k => TrieMap k a -> Maybe (TrieMap k a)-guardNullM m- | nullM m = Nothing- | otherwise = Just m--fillHoleM :: (TrieKey k, Sized a) => Maybe a -> Hole k a -> TrieMap k a-fillHoleM Nothing hole = clearM hole-fillHoleM (Just a) hole = assignM a hole--sides :: (b -> d) -> (a -> (# b, c, b #)) -> a -> (# d, c, d #)-sides g f a = case f a of- (# x, y, z #) -> (# g x, y, g z #)--both :: (b -> b') -> (c -> c') -> (a -> (# b, c #)) -> a -> (# b', c' #)-both g1 g2 f a = case f a of- (# x, y #) -> (# g1 x, g2 y #)--fmapM :: (TrieKey k, Sized b) => (a -> b) -> TrieMap k a -> TrieMap k b-fmapM = mapWithKeyM . const--assocsM :: TrieKey k => TrieMap k a -> [(k, a)]-assocsM m = build (\ f z -> foldrWithKeyM (\ k a xs -> (k, a) `f` xs) m z)--insertWithKeyM :: (TrieKey k, Sized a) => (k -> a -> a -> a) -> k -> a -> TrieMap k a -> TrieMap k a-insertWithKeyM f k a m = case searchM k m of- (# Nothing, hole #) -> assignM a hole- (# Just a', hole #) -> assignM (f k a a') hole--unionMaybe :: (a -> a -> Maybe a) -> Maybe a -> Maybe a -> Maybe a-unionMaybe _ Nothing y = y-unionMaybe _ x Nothing = x-unionMaybe f (Just x) (Just y) = f x y--isectMaybe :: (a -> b -> Maybe c) -> Maybe a -> Maybe b -> Maybe c-isectMaybe f (Just x) (Just y) = f x y-isectMaybe _ _ _ = Nothing--diffMaybe :: (a -> b -> Maybe a) -> Maybe a -> Maybe b -> Maybe a-diffMaybe _ Nothing _ = Nothing-diffMaybe _ (Just x) Nothing = Just x-diffMaybe f (Just x) (Just y) = f x y--subMaybe :: (a -> b -> Bool) -> Maybe a -> Maybe b -> Bool-subMaybe _ Nothing _ = True-subMaybe (<=) (Just a) (Just b) = a <= b-subMaybe _ _ _ = False
Data/TrieMap/UnionMap.hs view
@@ -1,130 +1,182 @@-{-# LANGUAGE PatternGuards, UnboxedTuples, TypeFamilies, PatternGuards, ViewPatterns, MagicHash #-}+{-# LANGUAGE UnboxedTuples, TypeFamilies, PatternGuards, ViewPatterns, MagicHash, CPP, BangPatterns #-} {-# OPTIONS -funbox-strict-fields #-} module Data.TrieMap.UnionMap () where import Data.TrieMap.TrieKey import Data.TrieMap.Sized+import Data.TrieMap.UnitMap () import Control.Applicative import Control.Monad +import Data.Foldable (foldr)+import Prelude hiding (foldr, (^)) import GHC.Exts (&) :: (TrieKey k1, TrieKey k2, Sized a) => TrieMap k1 a -> TrieMap k2 a -> TrieMap (Either k1 k2) a-m1 & m2- | nullM m1, nullM m2 = Empty- | otherwise = Union (getSize# m1 +# getSize# m2) m1 m2+m1 & m2 = guardNullM m1 ^ guardNullM m2 +{-# INLINE (^) #-}+(^) :: (TrieKey k1, TrieKey k2, Sized a) => Maybe (TrieMap k1 a) -> Maybe (TrieMap k2 a) -> TrieMap (Either k1 k2) a+Nothing ^ Nothing = Empty+Just m1 ^ Nothing = K1 m1+Nothing ^ Just m2 = K2 m2+Just m1 ^ Just m2 = Union (sizeM m1 +# sizeM m2) m1 m2++union :: (TrieKey k1, TrieKey k2, Sized a) => TrieMap k1 a -> TrieMap k2 a -> TrieMap (Either k1 k2) a+union m1 m2 = Union (getSize# m1 +# getSize# m2) m1 m2+ singletonL :: (TrieKey k1, TrieKey k2, Sized a) => k1 -> a -> TrieMap (Either k1 k2) a-singletonL k a = Union (getSize# a) (singletonM k a) emptyM+singletonL k a = K1 (singletonM k a) singletonR :: (TrieKey k1, TrieKey k2, Sized a) => k2 -> a -> TrieMap (Either k1 k2) a-singletonR k a = Union (getSize# a) emptyM (singletonM k a)+singletonR k a = K2 (singletonM k a) -instance (TrieKey k1, TrieKey k2) => TrieKey (Either k1 k2) where- data TrieMap (Either k1 k2) a = Empty | Union Int# (TrieMap k1 a) (TrieMap k2 a)- data Hole (Either k1 k2) a = - LHole (Hole k1 a) (TrieMap k2 a)- | RHole (TrieMap k1 a) (Hole k2 a)+data UView k1 k2 a = UView (Maybe (TrieMap k1 a)) (Maybe (TrieMap k2 a))+data HView k1 k2 a = Hole1 (Hole k1 a) (Maybe (TrieMap k2 a))+ | Hole2 (Maybe (TrieMap k1 a)) (Hole k2 a) +uView :: TrieMap (Either k1 k2) a -> UView k1 k2 a+uView Empty = UView Nothing Nothing+uView (K1 m1) = UView (Just m1) Nothing+uView (K2 m2) = UView Nothing (Just m2)+uView (Union _ m1 m2) = UView (Just m1) (Just m2)++hView :: Hole (Either k1 k2) a -> HView k1 k2 a+hView (HoleX0 hole1) = Hole1 hole1 Nothing+hView (HoleX2 hole1 m2) = Hole1 hole1 (Just m2)+hView (Hole0X hole2) = Hole2 Nothing hole2+hView (Hole1X m1 hole2) = Hole2 (Just m1) hole2++hole1 :: Hole k1 a -> Maybe (TrieMap k2 a) -> Hole (Either k1 k2) a+hole1 hole1 Nothing = HoleX0 hole1+hole1 hole1 (Just m2) = HoleX2 hole1 m2++hole2 :: Maybe (TrieMap k1 a) -> Hole k2 a -> Hole (Either k1 k2) a+hole2 Nothing hole2 = Hole0X hole2+hole2 (Just m1) hole2 = Hole1X m1 hole2++#define UVIEW uView -> UView++instance (TrieKey k1, TrieKey k2) => TrieKey (Either k1 k2) where+ {-# SPECIALIZE instance TrieKey (Either () ()) #-}+ {-# SPECIALIZE instance TrieKey k => TrieKey (Either () k) #-}+ {-# SPECIALIZE instance TrieKey k => TrieKey (Either k ()) #-}+ Left k1 =? Left k2 = k1 =? k2+ Right k1 =? Right k2 = k1 =? k2+ _ =? _ = False+ + Left k1 `cmp` Left k2 = k1 `cmp` k2+ Left{} `cmp` Right{} = LT+ Right k1 `cmp` Right k2 = k1 `cmp` k2+ Right{} `cmp` Left{} = GT+ + data TrieMap (Either k1 k2) a = + Empty+ | K1 (TrieMap k1 a)+ | K2 (TrieMap k2 a)+ | Union Int# (TrieMap k1 a) (TrieMap k2 a)+ data Hole (Either k1 k2) a =+ HoleX0 (Hole k1 a)+ | HoleX2 (Hole k1 a) (TrieMap k2 a)+ | Hole0X (Hole k2 a)+ | Hole1X (TrieMap k1 a) (Hole k2 a) emptyM = Empty singletonM = either singletonL singletonR - nullM Empty = True- nullM _ = False+ getSimpleM (UVIEW m1 m2) = mSimple m1 `mplus` mSimple m2 where+ mSimple :: TrieKey k => Maybe (TrieMap k a) -> Simple a+ mSimple = maybe mzero getSimpleM sizeM Empty = 0#+ sizeM (K1 m1) = sizeM m1+ sizeM (K2 m2) = sizeM m2 sizeM (Union s _ _) = s - lookupM k (Union _ m1 m2) = either (`lookupM` m1) (`lookupM` m2) k- lookupM _ _ = Nothing+ lookupM (Left k) (UVIEW m1 _) = m1 >>= lookupM k+ lookupM (Right k) (UVIEW _ m2) = m2 >>= lookupM k - traverseWithKeyM f (Union _ m1 m2) = (&) <$> traverseWithKeyM (f . Left) m1 <*> traverseWithKeyM (f . Right) m2- traverseWithKeyM _ _ = pure Empty+ traverseM f (Union _ m1 m2) = union <$> traverseM f m1 <*> traverseM f m2+ traverseM f (K1 m1) = K1 <$> traverseM f m1+ traverseM f (K2 m2) = K2 <$> traverseM f m2+ traverseM _ _ = pure Empty - foldrWithKeyM f (Union _ m1 m2) = foldrWithKeyM (f . Left) m1 . foldrWithKeyM (f . Right) m2- foldrWithKeyM _ _ = id+ foldrM f (UVIEW m1 m2) = fold (foldrM f) m1 . fold (foldrM f) m2+ where fold :: (a -> b -> b) -> Maybe a -> b -> b+ fold = flip . foldr - foldlWithKeyM f (Union _ m1 m2) = foldlWithKeyM (f . Right) m2 . foldlWithKeyM (f . Left) m1- foldlWithKeyM _ _ = id+ foldlM f (UVIEW m1 m2) = fold (foldlM f) m2 . fold (foldlM f) m1+ where fold :: (a -> b -> b) -> Maybe a -> b -> b+ fold = flip . foldr - mapWithKeyM f (Union _ m1 m2) = mapWithKeyM (f . Left) m1 & mapWithKeyM (f . Right) m2- mapWithKeyM _ _ = Empty+ fmapM f (Union _ m1 m2) = fmapM f m1 `union` fmapM f m2+ fmapM f (K1 m1) = K1 (fmapM f m1)+ fmapM f (K2 m2) = K2 (fmapM f m2)+ fmapM _ _ = Empty - mapMaybeM f (Union _ m1 m2) = mapMaybeM (f . Left) m1 & mapMaybeM (f . Right) m2- mapMaybeM _ _ = Empty+ mapMaybeM f (UVIEW m1 m2) = (m1 >>= mapMaybeM' f) ^ (m2 >>= mapMaybeM' f) - mapEitherM f (Union _ m1 m2)- | (# m1L, m1R #) <- mapEitherM (f . Left) m1,- (# m2L, m2R #) <- mapEitherM (f . Right) m2- = (# m1L & m2L, m1R & m2R #)- mapEitherM _ _ = (# Empty, Empty #)+ mapEitherM f (UVIEW m1 m2) = (# m1L ^ m2L, m1R ^ m2R #) where+ !(# m1L, m1R #) = mapEitherM'' f m1+ !(# m2L, m2R #) = mapEitherM'' f m2 - unionM f (Union _ m11 m12) (Union _ m21 m22)- = unionM (f . Left) m11 m21 & unionM (f . Right) m12 m22- unionM _ Empty m2 = m2- unionM _ m1 Empty = m1+ unionM _ Empty m2 = m2+ unionM f m1@(UVIEW m11 m12) m2@(UVIEW m21 m22)+ | Empty <- m2 = m1+ | otherwise = unionMaybe (unionM' f) m11 m21 ^ unionMaybe (unionM' f) m12 m22 - isectM _ Empty _ = Empty- isectM _ _ Empty = Empty- isectM f (Union _ m11 m12) (Union _ m21 m22)- = isectM (f . Left) m11 m21 & isectM (f . Right) m12 m22+ isectM f (UVIEW m11 m12) (UVIEW m21 m22) =+ isectMaybe (isectM' f) m11 m21 ^ isectMaybe (isectM' f) m12 m22 - diffM _ Empty _ = Empty- diffM _ m1 Empty = m1- diffM f (Union _ m11 m12) (Union _ m21 m22)- = diffM (f . Left) m11 m21 & diffM (f . Right) m12 m22+ diffM f m1@(UVIEW m11 m12) m2@(UVIEW m21 m22)+ | Empty <- m2 = m1+ | otherwise = diffMaybe (diffM' f) m11 m21 ^ diffMaybe (diffM' f) m12 m22 - isSubmapM _ Empty _ = True- isSubmapM (<=) (Union _ m11 m12) (Union _ m21 m22) = isSubmapM (<=) m11 m21 && isSubmapM (<=) m12 m22- isSubmapM _ Union{} Empty = False+ isSubmapM (<=) (UVIEW m11 m12) (UVIEW m21 m22) =+ subMaybe (isSubmapM (<=)) m11 m21 && subMaybe (isSubmapM (<=)) m12 m22 - fromListM f = onPair (&) (fromListM (f . Left)) (fromListM (f . Right)) . partEithers+ fromListM f = onPair (&) (fromListM f) (fromListM f) . partEithers - fromAscListM f = onPair (&) (fromAscListM (f . Left)) (fromAscListM (f . Right)) . partEithers+ fromAscListM f = onPair (&) (fromAscListM f) (fromAscListM f) . partEithers fromDistAscListM = onPair (&) fromDistAscListM fromDistAscListM . partEithers - singleHoleM (Left k) = LHole (singleHoleM k) emptyM- singleHoleM (Right k) = RHole emptyM (singleHoleM k)- - keyM (LHole holeL _) = Left (keyM holeL)- keyM (RHole _ holeR) = Right (keyM holeR)- - beforeM a (LHole holeL _) = let mL = beforeM a holeL in- if nullM mL then Empty else Union (getSize# mL) mL emptyM- beforeM a (RHole mL holeR) = mL & beforeM a holeR+ singleHoleM = either (HoleX0 . singleHoleM) (Hole0X . singleHoleM)++ beforeM a hole = case hView hole of+ Hole1 h1 __ -> beforeM' a h1 ^ Nothing+ Hole2 m1 h2 -> m1 ^ beforeM' a h2 - afterM a (LHole holeL mR) = afterM a holeL & mR- afterM a (RHole _ holeR) = let mR = afterM a holeR in- if nullM mR then Empty else Union (getSize# mR) emptyM mR+ afterM a hole = case hView hole of+ Hole1 h1 m2 -> afterM' a h1 ^ m2+ Hole2 __ h2 -> Nothing ^ afterM' a h2 - searchM k Empty = (# Nothing, singleHoleM k #)- searchM (Left k) (Union _ mL mR) = onUnboxed (`LHole` mR) (searchM k) mL- searchM (Right k) (Union _ mL mR) = onUnboxed (RHole mL) (searchM k) mR+ searchM (Left k) (UVIEW m1 m2) = onSnd (`hole1` m2) (searchM' k) m1+ searchM (Right k) (UVIEW m1 m2) = onSnd (hole2 m1) (searchM' k) m2 - indexM i# (Union _ mL mR)- | i# <# sL#, (# i'#, v, holeL #) <- indexM i# mL- = (# i'#, v, LHole holeL mR #)- | (# i'#, v, holeR #) <- indexM (i# -# sL#) mR- = (# i'#, v, RHole mL holeR #)- where !sL# = getSize# mL- indexM _ _ = (# error err, error err, error err #) where- err = "Error: empty trie"+ indexM i# (K1 m1) = onThird HoleX0 (indexM i#) m1+ indexM i# (K2 m2) = onThird Hole0X (indexM i#) m2+ indexM i# (Union _ m1 m2)+ | i# <# s1# = onThird (`HoleX2` m2) (indexM i#) m1+ | otherwise = onThird (Hole1X m1) (indexM (i# -# s1#)) m2+ where !s1# = sizeM m1+ indexM _ _ = indexFail () - extractHoleM (Union _ mL mR) = (do- (v, holeL) <- extractHoleM mL- return (v, LHole holeL mR)) `mplus` (do- (v, holeR) <- extractHoleM mR- return (v, RHole mL holeR))- extractHoleM _ = mzero+ extractHoleM (UVIEW m1 m2) = (do+ (v, h1) <- extractHoleM' m1+ return (v, hole1 h1 m2)) `mplus` (do+ (v, h2) <- extractHoleM' m2+ return (v, hole2 m1 h2)) - assignM v (LHole holeL mR) = assignM v holeL & mR- assignM v (RHole mL holeR) = mL & assignM v holeR-- clearM (LHole holeL mR) = clearM holeL & mR- clearM (RHole mL holeR) = mL & clearM holeR+ assignM v hole = case hView hole of+ Hole1 h1 m2 -> assignM' v h1 ^ m2+ Hole2 m1 h2 -> m1 ^ assignM' v h2+ + unifyM (Left k1) a1 (Left k2) a2 = either (Left . HoleX0) (Right . K1) (unifyM k1 a1 k2 a2)+ unifyM (Left k1) a1 (Right k2) a2 = Right $ singletonM k1 a1 `union` singletonM k2 a2+ unifyM (Right k2) a2 (Left k1) a1 = Right $ singletonM k1 a1 `union` singletonM k2 a2+ unifyM (Right k1) a1 (Right k2) a2 = either (Left . Hole0X) (Right . K2) (unifyM k1 a1 k2 a2) onPair :: (c -> d -> e) -> (a -> c) -> (b -> d) -> (a, b) -> e onPair f g h (a, b) = f (g a) (h b)
Data/TrieMap/UnitMap.hs view
@@ -15,41 +15,42 @@ import Prelude hiding (foldr, foldl) instance TrieKey () where+ _ =? _ = True+ _ `cmp` _ = EQ+ newtype TrieMap () a = Unit {getUnit :: Maybe a} data Hole () a = Hole emptyM = Unit Nothing singletonM _ = Unit . Just- nullM = isNothing . getUnit+ getSimpleM (Unit m) = maybe Null Singleton m sizeM (Unit (Just a)) = getSize# a sizeM _ = 0# lookupM _ (Unit m) = m- traverseWithKeyM f (Unit m) = Unit <$> traverse (f ()) m- foldrWithKeyM f (Unit m) z = foldr (f ()) z m- foldlWithKeyM f (Unit m) z = foldl (f ()) z m- mapWithKeyM f (Unit m) = Unit (f () <$> m)- mapMaybeM f (Unit m) = Unit (m >>= f ())- mapEitherM f (Unit (Just a)) = both Unit Unit (f ()) a- mapEitherM _ _ = (# emptyM, emptyM #)- unionM f (Unit m1) (Unit m2) = Unit (unionMaybe (f ()) m1 m2)- isectM f (Unit m1) (Unit m2) = Unit (isectMaybe (f ()) m1 m2)- diffM f (Unit m1) (Unit m2) = Unit (diffMaybe (f ()) m1 m2)+ traverseM f (Unit m) = Unit <$> traverse f m+ foldrM f (Unit m) z = foldr f z m+ foldlM f (Unit m) z = foldl f z m+ fmapM f (Unit m) = Unit (f <$> m)+ mapMaybeM f (Unit m) = Unit (m >>= f)+ mapEitherM f (Unit a) = both Unit Unit (mapEitherMaybe f) a+ unionM f (Unit m1) (Unit m2) = Unit (unionMaybe f m1 m2)+ isectM f (Unit m1) (Unit m2) = Unit (isectMaybe f m1 m2)+ diffM f (Unit m1) (Unit m2) = Unit (diffMaybe f m1 m2) isSubmapM (<=) (Unit m1) (Unit m2) = subMaybe (<=) m1 m2 fromListM _ [] = Unit Nothing- fromListM f ((_, v):xs) = Unit $ Just (foldl (\ v' -> f () v' . snd) v xs)+ fromListM f ((_, v):xs) = Unit $ Just (foldl (\ v' -> f v' . snd) v xs) singleHoleM _ = Hole- keyM _ = () beforeM a _ = Unit a afterM a _ = Unit a searchM _ (Unit m) = (# m, Hole #) indexM i (Unit (Just v)) = (# i, v, Hole #)- indexM _ _ = (# error err, error err, error err #) where- err = "Error: empty trie"+ indexM _ _ = indexFail () + unifyM _ _ _ _ = Left Hole+ extractHoleM (Unit (Just v)) = return (v, Hole) extractHoleM _ = mzero - assignM v _ = Unit (Just v)- clearM _ = emptyM+ assignM v _ = Unit v
+ Data/TrieMap/Utils.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE Rank2Types, BangPatterns, MagicHash #-}+module Data.TrieMap.Utils (toVectorN, toVectorF) where++import Data.Vector.Generic+import Data.Vector.Generic.Mutable+import qualified Data.Foldable+import GHC.Exts++{-# INLINE toVectorN #-}+toVectorN :: Vector v a => (forall b . (a -> b -> b) -> b -> f -> b) -> (f -> Int) -> f -> v a+toVectorN fold size xs = create $ do+ !mv <- unsafeNew (size xs)+ fold (\ x m i# -> unsafeWrite mv (I# i#) x >> m (i# +# 1#)) (\ _ -> return mv) xs 0#++{-# INLINE toVectorF #-}+toVectorF :: (Vector v b, Data.Foldable.Foldable f) => (a -> b) -> (f a -> Int) -> f a -> v b+toVectorF g = toVectorN (\ f -> Data.Foldable.foldr (f . g))
Tests.hs view
@@ -2,15 +2,19 @@ -- module Tests where import Control.Monad+import Debug.Trace+import Data.TrieMap.Class+import Data.TrieMap.TrieKey+import Data.TrieMap.Sized import qualified Data.TrieMap as T import qualified Data.Map as M import Test.QuickCheck import Prelude hiding (null, lookup) -type Key = [Int]-type Val = [Int]+type Key = Integer+type Val = [Integer] -main = quickCheckWith stdArgs{maxSize = 800, maxSuccess = 800} (verify M.empty T.empty)+main = quickCheckWith stdArgs{maxSize = 300, maxSuccess = 100} (verify M.empty T.empty) instance Arbitrary Op where arbitrary = oneof [@@ -30,7 +34,7 @@ shrink (Op (Insert k v)) = [Op (Insert k' v') | k' <- shrink k, v' <- shrink v] shrink (Op (Lookup k)) = map (Op . Lookup) (shrink k) shrink (Op (Delete k)) = map (Op . Delete) (shrink k)- shrink (Op (Union ops)) = map (Op . Union) (shrink ops)+ shrink (Op (Union ops)) = ops ++ map (Op . Union) (shrink ops) shrink _ = [] recurse :: Gen [Op]@@ -51,6 +55,7 @@ show (Op (Union ops)) = "Union " ++ show ops show (Op (DeleteAt i)) = "DeleteAt " ++ show i show (Op (ElemAt i)) = "ElemAt " ++ show i+ show (Op (Isect ops)) = "Isect " ++ show ops data Operation r where Insert :: Key -> Val -> Operation ()@@ -68,15 +73,15 @@ ElemAt :: Int -> Operation (Maybe (Key, Val)) mapFunc :: Key -> Val -> Val-mapFunc = (++)+mapFunc = (:) mapMaybeFunc :: Key -> Val -> Maybe Val-mapMaybeFunc (k:ks) xs- | even k = Just (ks ++ xs)+mapMaybeFunc k xs+ | even k = Just (k:xs) mapMaybeFunc _ _ = Nothing isectFunc :: Key -> Val -> Val -> Val-isectFunc ks xs ys = ks ++ xs ++ ys+isectFunc ks xs ys = ks:xs ++ ys generateMap :: M.Map Key Val -> [Op] -> M.Map Key Val generateMap = foldl (\ mm (Op op) -> snd (operateMap mm op))
TrieMap.cabal view
@@ -1,39 +1,53 @@ name: TrieMap-version: 1.5.0+version: 2.0.0 tested-with: GHC category: Algorithms synopsis: Automatic type inference of generalized tries with Template Haskell. description: Provides a efficient and compact implementation of generalized tries, and Template Haskell tools to generate the necessary translation code. This is meant as a drop-in replacement for Data.Map.+ + The most recent release combines zipper-based ideas from recently proposed changes to Data.Map, as well+ as heavily optimized ByteString and Vector instances based on the vector package. license: BSD3 license-file: LICENSE author: Louis Wasserman maintainer: wasserman.louis@gmail.com-build-Depends: base < 5.0.0.0, containers, template-haskell, bytestring, array, th-expand-syns, ghc-prim+build-Depends: base < 5.0.0.0, containers, template-haskell, bytestring, th-expand-syns, ghc-prim, vector, primitive build-type: Simple-ghc-options: -Wall -fno-warn-name-shadowing -fno-warn-orphans+ghc-options: -Wall -fno-warn-name-shadowing -fno-warn-orphans -O2 -fno-spec-constr-count -fno-spec-constr-threshold+ -fno-liberate-case-threshold -fmax-worker-args=100 extra-source-files: Tests.hs exposed-modules: Data.TrieMap, Data.TrieSet,+ Data.TrieMap.Class, Data.TrieMap.Representation,- Data.TrieMap.Representation.TH, Data.TrieMap.Modifiers other-modules:- Data.TrieMap.Class,- Data.TrieMap.Class.Instances,- Data.TrieMap.Key,- Data.TrieMap.TrieKey,+ Data.TrieMap.Utils,+ Data.TrieMap.Sized, Data.TrieMap.Applicative,- Data.TrieMap.ProdMap,- Data.TrieMap.RadixTrie,- Data.TrieMap.UnionMap,- Data.TrieMap.UnitMap,- Data.TrieMap.Rep,- Data.TrieMap.Rep.Instances,- Data.TrieMap.Rep.TH,+ Data.TrieMap.Representation.Class,+ Data.TrieMap.Representation.TH,+ Data.TrieMap.Representation.TH.Utils,+ Data.TrieMap.Representation.TH.Representation,+ Data.TrieMap.Representation.TH.Factorized,+ Data.TrieMap.Representation.TH.ReprMonad,+ Data.TrieMap.Representation.Instances,+ Data.TrieMap.Representation.Instances.Basic,+ Data.TrieMap.Representation.Instances.Prim,+ Data.TrieMap.Representation.Instances.Foreign,+ Data.TrieMap.Representation.Instances.Vectors,+ Data.TrieMap.Representation.Instances.ByteString Data.TrieMap.IntMap, Data.TrieMap.OrdMap,+ Data.TrieMap.UnitMap,+ Data.TrieMap.ProdMap,+ Data.TrieMap.UnionMap, Data.TrieMap.ReverseMap,- Data.TrieMap.Sized,- Data.TrieMap.Applicative+ Data.TrieMap.Key,+ Data.TrieMap.RadixTrie,+ Data.TrieMap.RadixTrie.Slice,+ Data.TrieMap.RadixTrie.Edge,+ Data.TrieMap.Class.Instances+