module Data.StringMap.Base
(
StringMap (..)
, Key
, Key1(..)
, (!)
, value
, valueWithDefault
, null
, size
, member
, lookup
, findWithDefault
, prefixFind
, prefixFindWithKey
, prefixFindWithKeyBF
, lookupGE
, lookupLE
, lookupRange
, empty
, singleton
, insert
, insertWith
, insertWithKey
, adjust
, adjustWithKey
, delete
, update
, updateWithKey
, union
, unionWith
, unionMapWith
, unionWithKey
, difference
, differenceWith
, differenceWithKey
, intersection
, intersectionWith
, map
, mapWithKey
, mapM
, mapWithKeyM
, mapMaybe
, fold
, foldWithKey
, foldl
, foldlWithKey
, foldr
, foldrWithKey
, keys
, elems
, fromList
, toList
, toListShortestFirst
, fromMap
, toMap
, cutPx'
, cutAllPx'
, branch
, val
, siseq
, fromKey
, toKey
, norm
, normError'
, unNorm
, deepUnNorm
, deepNorm
, visit
, StringMapVisitor(..)
)
where
import Prelude hiding (foldl, foldr, lookup, map,
mapM, null, succ)
import Control.Applicative (pure, (<$>), (<*>))
import Control.Arrow
import Control.DeepSeq
import Data.Binary
import qualified Data.Foldable as F
import qualified Data.List as L
import qualified Data.Map as M
import Data.Maybe hiding (mapMaybe)
import Data.StringMap.StringSet
import Data.StringMap.Types
import qualified Data.Traversable as T
import Data.Typeable
#if sizeable
import Data.Size
#endif
data StringMap v = Empty
| Val { value' :: v
, tree :: ! (StringMap v)
}
| Branch { sym ::
! Sym
, child :: ! (StringMap v)
, next :: ! (StringMap v)
}
| Leaf { value' :: v
}
| Last { sym ::
! Sym
, child :: ! (StringMap v)
}
| LsSeq { syms :: ! Key1
, child :: ! (StringMap v)
}
| BrSeq { syms :: ! Key1
, child :: ! (StringMap v)
, next :: ! (StringMap v)
}
| LsSeL { syms :: ! Key1
, value' :: v
}
| BrSeL { syms :: ! Key1
, value' :: v
, next :: ! (StringMap v)
}
| BrVal { sym ::
! Sym
, value' :: v
, next :: ! (StringMap v)
}
| LsVal { sym ::
! Sym
, value' :: v
}
deriving (Show, Eq, Ord, Typeable)
data Key1 = Nil
| S1 ! Sym
| S2 ! Sym ! Sym
| S3 ! Sym ! Sym ! Sym
| S4 ! Sym ! Sym ! Sym ! Sym
| C1 ! Sym
! Key1
| C2 ! Sym ! Sym
! Key1
| C3 ! Sym ! Sym ! Sym
! Key1
| C4 ! Sym ! Sym ! Sym ! Sym
! Key1
deriving (Eq, Ord, Typeable)
instance Show Key1 where
show k = show (toKey k)
mk1 :: Sym -> Key1
mk1 s1 = S1 s1
mk2 :: Sym -> Sym -> Key1
mk2 s1 s2 = S2 s1 s2
mk3 :: Sym -> Sym -> Sym -> Key1
mk3 s1 s2 s3 = S3 s1 s2 s3
mk4 :: Sym -> Sym -> Sym -> Sym -> Key1
mk4 s1 s2 s3 s4 = S4 s1 s2 s3 s4
cons1 :: Sym -> Key1 -> Key1
cons1 s Nil = mk1 s
cons1 s (S1 s2) = mk2 s s2
cons1 s (S2 s2 s3) = mk3 s s2 s3
cons1 s (S3 s2 s3 s4) = mk4 s s2 s3 s4
cons1 s (C1 s2 k2) = C2 s s2 k2
cons1 s (C2 s2 s3 k3) = C3 s s2 s3 k3
cons1 s (C3 s2 s3 s4 k4) = C4 s s2 s3 s4 k4
cons1 s k = C1 s k
uncons1 :: Key1 -> (Sym, Key1)
uncons1 (S1 s) = (s, Nil)
uncons1 (S2 s s2) = (s, mk1 s2)
uncons1 (S3 s s2 s3) = (s, mk2 s2 s3)
uncons1 (S4 s s2 s3 s4) = (s, mk3 s2 s3 s4)
uncons1 (C1 s k1) = (s, k1)
uncons1 (C2 s s2 k1) = (s, C1 s2 k1)
uncons1 (C3 s s2 s3 k1) = (s, C2 s2 s3 k1)
uncons1 (C4 s s2 s3 s4 k1) = (s, C3 s2 s3 s4 k1)
uncons1 Nil = error "uncons1 with Nil"
toKey :: Key1 -> Key
toKey (S2 s1 s2 ) = s1 : s2 : []
toKey (S3 s1 s2 s3 ) = s1 : s2 : s3 : []
toKey (S4 s1 s2 s3 s4) = s1 : s2 : s3 : s4 : []
toKey (S1 s1 ) = s1 : []
toKey (C1 s1 k) = s1 : toKey k
toKey (C2 s1 s2 k) = s1 : s2 : toKey k
toKey (C3 s1 s2 s3 k) = s1 : s2 : s3 : toKey k
toKey (C4 s1 s2 s3 s4 k) = s1 : s2 : s3 : s4 : toKey k
toKey Nil = []
fromKey :: Key -> Key1
fromKey k1 = L.foldr cons1 Nil k1
empty :: StringMap v
empty = Empty
val :: v -> StringMap v -> StringMap v
val v Empty = Leaf v
val v t = Val v t
branch :: Sym -> StringMap v -> StringMap v -> StringMap v
branch !_k Empty n = n
branch !k (Leaf v ) Empty = LsVal k v
branch !k (LsVal k1 v) Empty = LsSeL (mk2 k k1) v
branch !k (LsSeL ks v) Empty = LsSeL (cons1 k ks) v
branch !k (Last k1 c) Empty = lsseq (mk2 k k1) c
branch !k (LsSeq ks c) Empty = lsseq (cons1 k ks) c
branch !k c Empty = Last k c
branch !k (Leaf v ) n = BrVal k v n
branch !k (LsVal k1 v) n = BrSeL (mk2 k k1) v n
branch !k (LsSeL ks v) n = BrSeL (cons1 k ks) v n
branch !k (Last k1 c) n = brseq (mk2 k k1) c n
branch !k (LsSeq ks c) n = brseq (cons1 k ks) c n
branch !k c n = Branch k c n
lsseq :: Key1 -> StringMap v -> StringMap v
lsseq !k (Leaf v) = LsSeL k v
lsseq !k c = LsSeq k c
brseq :: Key1 -> StringMap v -> StringMap v -> StringMap v
brseq !k (Leaf v) n = BrSeL k v n
brseq !k c n = BrSeq k c n
siseq :: Key1 -> StringMap v -> StringMap v
siseq Nil c = c
siseq k c = case uncons1 k of
(k1, Nil) -> Last k1 c
_ -> LsSeq k c
anyseq :: Key1 -> StringMap v -> StringMap v
anyseq Nil c = c
anyseq k (Leaf v) = case uncons1 k of
(k1, Nil) -> LsVal k1 v
_ -> LsSeL k v
anyseq k c = case uncons1 k of
(k1, Nil) -> Last k1 c
_ -> LsSeq k c
norm :: StringMap v -> StringMap v
norm (Leaf v) = Val v empty
norm (Last k c) = Branch k c empty
norm (LsSeq k' c) = case uncons1 k' of
(k, Nil) -> Branch k c empty
(k, ks) -> Branch k (siseq ks c) empty
norm (BrSeq k' c n) = case uncons1 k' of
(k, Nil) -> Branch k c n
(k, ks) -> Branch k (siseq ks c) n
norm (LsSeL ks v) = norm (LsSeq ks (val v empty))
norm (BrSeL ks v n) = norm (BrSeq ks (val v empty) n)
norm (LsVal k v) = norm (LsSeq (mk1 k) (val v empty))
norm (BrVal k v n) = norm (BrSeq (mk1 k) (val v empty) n)
norm t = t
unNorm :: StringMap v -> StringMap v
unNorm t = case norm t of
(Branch k c n) -> branch k c n
(Val v t') -> val v t'
t' -> t'
deepUnNorm :: StringMap v -> StringMap v
deepUnNorm t = case norm t of
(Branch k c n) -> branch k (deepUnNorm c) (deepUnNorm n)
(Val v t') -> val v (deepUnNorm t')
t' -> t'
deepNorm :: StringMap v -> StringMap v
deepNorm t0
= case norm t0 of
Empty -> Empty
Val v t -> Val v (deepNorm t)
Branch c s n -> Branch c (deepNorm s) (deepNorm n)
_ -> normError "deepNorm"
normError' :: String -> String -> a
normError' m f = error (m ++ "." ++ f ++ ": pattern match error, prefix tree not normalized")
normError :: String -> a
normError = normError' "Data.StringMap.Base"
null :: StringMap a -> Bool
null Empty = True
null _ = False
singleton :: Key -> a -> StringMap a
singleton k v = anyseq (fromKey k) (val v empty)
value :: Monad m => StringMap a -> m a
value t = case norm t of
Val v _ -> return v
_ -> fail "StringMap.value: no value at this node"
valueWithDefault :: a -> StringMap a -> a
valueWithDefault d t = fromMaybe d . value $ t
lookup :: Monad m => Key -> StringMap a -> m a
lookup k t = case lookup' k t of
Just v -> return v
Nothing -> fail "StringMap.lookup: Key not found"
findWithDefault :: a -> Key -> StringMap a -> a
findWithDefault v0 k = fromMaybe v0 . lookup' k
member :: Key -> StringMap a -> Bool
member k = isJust . lookup k
(!) :: StringMap a -> Key -> a
(!) = flip $ findWithDefault (error "StringMap.! : element not in the map")
insert :: Key -> a -> StringMap a -> StringMap a
insert = insertWith const
insertWith :: (a -> a -> a) -> Key -> a -> StringMap a -> StringMap a
insertWith f = flip $ insert' f
insertWithKey :: (Key -> a -> a -> a) -> Key -> a -> StringMap a -> StringMap a
insertWithKey f k = insertWith (f k) k
update :: (a -> Maybe a) -> Key -> StringMap a -> StringMap a
update = update'
updateWithKey :: (Key -> a -> Maybe a) -> Key -> StringMap a -> StringMap a
updateWithKey f k = update' (f k) k
delete :: Key -> StringMap a -> StringMap a
delete = update' (const Nothing)
adjust :: (a -> a) -> Key -> StringMap a -> StringMap a
adjust f = update' (Just . f)
adjustWithKey :: (Key -> a -> a) -> Key -> StringMap a -> StringMap a
adjustWithKey f k = update' (Just . f k) k
lookupPx' :: Key -> StringMap a -> StringMap a
lookupPx' k0 = look k0 . norm
where
look [] t = t
look k@(c : k1) (Branch c' s' n')
| c < c' = empty
| c == c' = lookupPx' k1 s'
| otherwise = lookupPx' k n'
look _ Empty = empty
look k (Val _v' t') = lookupPx' k t'
look _ _ = normError "lookupPx'"
lookup' :: Key -> StringMap a -> Maybe a
lookup' k t
= case lookupPx' k t of
Val v _ -> Just v
_ -> Nothing
lookupGE :: Key -> StringMap a -> StringMap a
lookupGE k0 = look k0 . norm
where
look [] t = t
look k@(c : k1) t@(Branch c' s' n')
| c < c' = t
| c == c' = branch c' (lookupGE k1 s') n'
| otherwise = lookupGE k n'
look _ Empty = empty
look k (Val _v' t') = lookupGE k t'
look _ _ = normError "lookupGE"
lookupLE :: Key -> StringMap a -> StringMap a
lookupLE k0 = look k0 . norm
where
look [] (Val v' _t') = (Val v' empty)
look [] _t = empty
look k@(c : k1) (Branch c' s' n')
| c < c' = empty
| c == c' = branch c' (lookupLE k1 s') empty
| otherwise = branch c' s' (lookupLE k n')
look _ Empty = empty
look k (Val v' t') = val v' (lookupLE k t')
look _ _ = normError "lookupLE"
lookupRange :: Key -> Key -> StringMap a -> StringMap a
lookupRange lb ub = lookupLE ub . lookupGE lb
prefixFind :: Key -> StringMap a -> [a]
prefixFind k = elems . lookupPx' k
prefixFindWithKey :: Key -> StringMap a -> [(Key, a)]
prefixFindWithKey k = fmap (first (k ++)) . toList . lookupPx' k
insert' :: (a -> a -> a) -> a -> Key -> StringMap a -> StringMap a
insert' f v k0 = ins k0 . norm
where
ins' = insert' f v
ins k (Branch c' s' n')
= case k of
[] -> val v (branch c' s' n')
(c : k1)
| c < c' -> branch c (singleton k1 v) (branch c' s' n')
| c == c' -> branch c (ins' k1 s') n'
| otherwise -> branch c' s' (ins' k n')
ins k Empty = singleton k v
ins k (Val v' t')
= case k of
[] -> val (f v v') t'
_ -> val v' (ins' k t')
ins _ _ = normError "insert'"
update' :: (a -> Maybe a) -> Key -> StringMap a -> StringMap a
update' f k0 = upd k0 . norm
where
upd' = update' f
upd k (Branch c' s' n')
= case k of
[] -> branch c' s' n'
(c : k1)
| c < c' -> branch c' s' n'
| c == c' -> branch c (upd' k1 s') n'
| otherwise -> branch c' s' (upd' k n')
upd _ Empty = empty
upd k (Val v' t')
= case k of
[] -> maybe t' (flip val t') $ f v'
_ -> val v' (upd' k t')
upd _ _ = normError "update'"
union :: StringMap a -> StringMap a -> StringMap a
union = union' const
unionWith :: (a -> a -> a) -> StringMap a -> StringMap a -> StringMap a
unionWith = union'
union' :: (a -> a -> a) -> StringMap a -> StringMap a -> StringMap a
union' f pt1 pt2 = uni (norm pt1) (norm pt2)
where
uni' t1' t2' = union' f (norm t1') (norm t2')
uni Empty Empty = empty
uni Empty (Val v2 t2) = val v2 t2
uni Empty (Branch c2 s2 n2)
= branch c2 s2 n2
uni (Val v1 t1) Empty = val v1 t1
uni (Val v1 t1) (Val v2 t2) = val (f v1 v2) (uni' t1 t2)
uni (Val v1 t1) t2@(Branch _ _ _) = val v1 (uni' t1 t2)
uni (Branch c1 s1 n1) Empty = branch c1 s1 n1
uni t1@(Branch _ _ _ ) (Val v2 t2) = val v2 (uni' t1 t2)
uni t1@(Branch c1 s1 n1) t2@(Branch c2 s2 n2)
| c1 < c2 = branch c1 s1 (uni' n1 t2)
| c1 > c2 = branch c2 s2 (uni' t1 n2)
| otherwise = branch c1 (uni' s1 s2) (uni' n1 n2)
uni _ _ = normError "union'"
unionMapWith :: (b -> a) -> (a -> b -> a) -> StringMap a -> StringMap b -> StringMap a
unionMapWith = unionG'
unionG' :: (b -> a) -> (a -> b -> a) -> StringMap a -> StringMap b -> StringMap a
unionG' to f pt1 pt2 = uni (norm pt1) (norm pt2)
where
uni' t1' t2' = unionG' to f (norm t1') (norm t2')
uni Empty Empty = empty
uni Empty (Val v2 t2) = val (to v2) (map to t2)
uni Empty (Branch c2 s2 n2)
= branch c2 (map to s2) (map to n2)
uni (Val v1 t1) Empty = val v1 t1
uni (Val v1 t1) (Val v2 t2) = val (f v1 v2) (uni' t1 t2)
uni (Val v1 t1) t2@(Branch _ _ _) = val v1 (uni' t1 t2)
uni (Branch c1 s1 n1) Empty = branch c1 s1 n1
uni t1@(Branch _ _ _ ) (Val v2 t2) = val (to v2) (uni' t1 t2)
uni t1@(Branch c1 s1 n1) t2@(Branch c2 s2 n2)
| c1 < c2 = branch c1 s1 (uni' n1 t2)
| c1 > c2 = branch c2 (map to s2) (uni' t1 n2)
| otherwise = branch c1 (uni' s1 s2) (uni' n1 n2)
uni _ _ = normError "union'"
unionWithKey :: (Key -> a -> a -> a) -> StringMap a -> StringMap a -> StringMap a
unionWithKey f = union'' f id
union'' :: (Key -> a -> a -> a) -> (Key -> Key) -> StringMap a -> StringMap a -> StringMap a
union'' f kf pt1 pt2 = uni (norm pt1) (norm pt2)
where
uni' t1' t2' = union'' f kf (norm t1') (norm t2')
uni Empty Empty = empty
uni Empty (Val v2 t2) = val v2 t2
uni Empty (Branch c2 s2 n2)
= branch c2 s2 n2
uni (Val v1 t1) Empty = val v1 t1
uni (Val v1 t1) (Val v2 t2) = val (f (kf []) v1 v2) (uni' t1 t2)
uni (Val v1 t1) t2@(Branch _ _ _) = val v1 (uni' t1 t2)
uni (Branch c1 s1 n1) Empty = branch c1 s1 n1
uni t1@(Branch _ _ _ ) (Val v2 t2) = val v2 (uni' t1 t2)
uni t1@(Branch c1 s1 n1) t2@(Branch c2 s2 n2)
| c1 < c2 = branch c1 s1 (uni' n1 t2)
| c1 > c2 = branch c2 s2 (uni' t1 n2)
| otherwise = branch c1 (union'' f (kf . (c1:)) s1 s2) (uni' n1 n2)
uni _ _ = normError "union''"
difference :: StringMap a -> StringMap b -> StringMap a
difference = differenceWith (const (const Nothing))
differenceWith :: (a -> b -> Maybe a) -> StringMap a -> StringMap b -> StringMap a
differenceWith f = differenceWithKey (const f)
differenceWithKey :: (Key -> a -> b -> Maybe a) -> StringMap a -> StringMap b -> StringMap a
differenceWithKey f = diff'' f id
diff'' :: (Key -> a -> b -> Maybe a) ->
(Key -> Key) ->
StringMap a -> StringMap b -> StringMap a
diff'' f kf pt1 pt2 = dif (norm pt1) (norm pt2)
where
dif' t1' t2' = diff'' f kf (norm t1') (norm t2')
dif Empty _ = empty
dif (Val v1 t1) Empty = val v1 t1
dif (Val v1 t1) (Val v2 t2) =
case f (kf []) v1 v2 of
Nothing -> dif' t1 t2
Just nv -> val nv (dif' t1 t2)
dif (Val v1 t1) t2@(Branch _ _ _) = val v1 (dif' t1 t2)
dif (Branch c1 s1 n1) Empty = branch c1 s1 n1
dif t1@(Branch _ _ _ ) (Val _ t2) = dif' t1 t2
dif t1@(Branch c1 s1 n1) t2@(Branch c2 s2 n2)
| c1 < c2 = branch c1 s1 (dif' n1 t2)
| c1 > c2 = dif' t1 n2
| otherwise = branch c1 (diff'' f (kf . (c1:)) s1 s2) (dif' n1 n2)
dif _ _ = normError "diff''"
intersection :: StringMap a -> StringMap a -> StringMap a
intersection t1 t2 = intersectionWith const t1 t2
intersectionWith :: (a -> b -> c) -> StringMap a -> StringMap b -> StringMap c
intersectionWith f tree1 tree2 = intersection' (norm tree1) (norm tree2)
where
intersection'' t1' t2' = intersection' (norm t1') (norm t2')
intersection' Empty _ = empty
intersection' _ Empty = empty
intersection' (Val v1 t1) (Val v2 t2) = val (f v1 v2) $ intersection'' t1 t2
intersection' (Val _ t1) t2@(Branch _ _ _) = intersection'' t1 t2
intersection' t1@(Branch _ _ _) (Val _ t2) = intersection'' t1 t2
intersection' t1@(Branch c1 s1 n1) t2@(Branch c2 s2 n2)
| c1 < c2 = intersection'' n1 t2
| c1 > c2 = intersection'' t1 n2
| otherwise = branch c1 (intersection'' s1 s2) (intersection'' n1 n2)
intersection' _ _ = normError "intersectionWith"
cutPx'' :: (StringMap a -> StringMap a) -> StringSet -> StringMap a -> StringMap a
cutPx'' cf s1' t2' = cut s1' (norm t2')
where
cut PSempty _t2 = empty
cut (PSelem _s1) t2 = cf t2
cut (PSnext _ _ _ ) Empty = empty
cut t1@(PSnext _ _ _ ) (Val _ t2) = cut t1 (norm t2)
cut t1@(PSnext c1 s1 n1) t2@(Branch c2 s2 n2)
| c1 < c2 = cut n1 t2
| c1 > c2 = cut t1 (norm n2)
| otherwise = branch c1 (cutPx'' cf s1 s2) (cutPx'' cf n1 n2)
cut _ _ = normError "cutPx''"
cutPx' :: StringSet -> StringMap a -> StringMap a
cutPx' = cutPx'' id
cutAllPx' :: StringSet -> StringMap a -> StringMap a
cutAllPx' = cutPx'' (cv . norm)
where
cv (Val v _) = val v empty
cv _ = empty
map :: (a -> b) -> StringMap a -> StringMap b
map f = mapWithKey (const f)
mapWithKey :: (Key -> a -> b) -> StringMap a -> StringMap b
mapWithKey f = map' f id
map' :: (Key -> a -> b) -> (Key -> Key) -> StringMap a -> StringMap b
map' f = mp'
where
mp' k = mp
where
f' = f (k [])
mp (Empty) = Empty
mp (Val v t) = Val (f' v) (mp t)
mp (Branch c s n) = Branch c (mp' ((c :) . k) s) (mp n)
mp (Leaf v) = Leaf (f' v)
mp (Last c s) = Last c (mp' ((c :) . k) s)
mp (LsSeq cs s) = LsSeq cs (mp' ((toKey cs ++) . k) s)
mp (BrSeq cs s n) = BrSeq cs (mp' ((toKey cs ++) . k) s) (mp n)
mp (LsSeL cs v) = LsSeL cs (f' v)
mp (BrSeL cs v n) = BrSeL cs (f' v) (mp n)
mp (LsVal c v) = LsVal c (f' v)
mp (BrVal c v n) = BrVal c (f' v) (mp n)
mapMaybe :: (a -> Maybe b) -> StringMap a -> StringMap b
mapMaybe = mapMaybe'
mapMaybe' :: (a -> Maybe b) -> StringMap a -> StringMap b
mapMaybe' f = upd . norm
where
upd' = mapMaybe' f
upd (Branch c' s' n') = branch c' (upd' s') (upd' n')
upd Empty = empty
upd (Val v' t') = maybe t (flip val t) $ f v'
where t = upd' t'
upd _ = normError "update'"
mapM :: Monad m => (a -> m b) -> StringMap a -> m (StringMap b)
mapM f = mapWithKeyM (const f)
mapWithKeyM :: Monad m => (Key -> a -> m b) -> StringMap a -> m (StringMap b)
mapWithKeyM f = mapM'' f id
mapM'' :: Monad m => (Key -> a -> m b) -> (Key -> Key) -> StringMap a -> m (StringMap b)
mapM'' f k = mapn . norm
where
mapn Empty = return $ empty
mapn (Val v t) = do
v' <- f (k []) v
t' <- mapM'' f k t
return $ val v' t'
mapn (Branch c s n) = do
s' <- mapM'' f ((c :) . k) s
n' <- mapM'' f k n
return $ branch c s' n'
mapn _ = normError "mapM''"
data StringMapVisitor a b = PTV
{ v_empty :: b
, v_val :: a -> b -> b
, v_branch :: Sym -> b -> b -> b
, v_leaf :: a -> b
, v_last :: Sym -> b -> b
, v_lsseq :: Key1 -> b -> b
, v_brseq :: Key1 -> b -> b -> b
, v_lssel :: Key1 -> a -> b
, v_brsel :: Key1 -> a -> b -> b
, v_lsval :: Sym -> a -> b
, v_brval :: Sym -> a -> b -> b
}
visit :: StringMapVisitor a b -> StringMap a -> b
visit v (Empty) = v_empty v
visit v (Val v' t) = v_val v v' (visit v t)
visit v (Branch c s n) = v_branch v c (visit v s) (visit v n)
visit v (Leaf v') = v_leaf v v'
visit v (Last c s) = v_last v c (visit v s)
visit v (LsSeq cs s) = v_lsseq v cs (visit v s)
visit v (BrSeq cs s n) = v_brseq v cs (visit v s) (visit v n)
visit v (LsSeL cs v') = v_lssel v cs v'
visit v (BrSeL cs v' n) = v_brsel v cs v' (visit v n)
visit v (LsVal c v') = v_lsval v c v'
visit v (BrVal c v' n) = v_brval v c v' (visit v n)
foldWithKey :: (Key -> a -> b -> b) -> b -> StringMap a -> b
foldWithKey f e = rfold' f e id
foldrWithKey :: (Key -> a -> b -> b) -> b -> StringMap a -> b
foldrWithKey f e = rfold' f e id
fold :: (a -> b -> b) -> b -> StringMap a -> b
fold f = foldWithKey $ const f
foldr :: (a -> b -> b) -> b -> StringMap a -> b
foldr f = foldrWithKey $ const f
rfold' :: (Key -> a -> b -> b) -> b -> (Key -> Key) -> StringMap a -> b
rfold' f r k0 = fo k0 . norm
where
fo kf (Branch c' s' n') = let r' = rfold' f r kf n' in rfold' f r' (kf . (c':)) s'
fo _ (Empty) = r
fo kf (Val v' t') = let r' = rfold' f r kf t' in f (kf []) v' r'
fo _ _ = normError "rfold'"
foldl :: (b -> a -> b) -> b -> StringMap a -> b
foldl f = foldlWithKey $ \ x -> const (f x)
foldlWithKey :: (b -> Key -> a -> b) -> b -> StringMap a -> b
foldlWithKey f e = lfold' f e id
lfold' :: (b -> Key -> a -> b) -> b -> (Key -> Key) -> StringMap a -> b
lfold' f r k0 = fo k0 . norm
where
fo kf (Branch c' s' n') = let r' = lfold' f r (kf . (c':)) s' in lfold' f r' kf n'
fo _ (Empty) = r
fo kf (Val v' t') = let r' = f r (kf []) v' in lfold' f r' kf t'
fo _ _ = normError "lfold'"
toMap :: StringMap a -> M.Map Key a
toMap = foldWithKey M.insert M.empty
fromMap :: M.Map Key a -> StringMap a
fromMap = M.foldrWithKey insert empty
toList :: StringMap a -> [(Key, a)]
toList = foldWithKey (\k v r -> (k, v) : r) []
fromList :: [(Key, a)] -> StringMap a
fromList = L.foldl' (\p (k, v) -> insert k v p) empty
size :: StringMap a -> Int
size = fold (const (+1)) 0
elems :: StringMap a -> [a]
elems = fold (:) []
keys :: StringMap a -> [Key]
keys = foldWithKey (\ k _v r -> k : r) []
toListShortestFirst :: StringMap v -> [(Key, v)]
toListShortestFirst = (\ t0 -> [(id, t0)])
>>>
iterate (concatMap (second norm >>> uncurry subForest))
>>>
takeWhile (not . L.null)
>>>
concat
>>>
concatMap (second norm >>> uncurry rootLabel)
rootLabel :: (Key -> Key) -> StringMap v -> [(Key, v)]
rootLabel kf (Val v _) = [(kf [], v)]
rootLabel _ _ = []
subForest :: (Key -> Key) -> StringMap v -> [(Key -> Key, StringMap v)]
subForest kf (Branch c s n) = (kf . (c:), s) : subForest kf (norm n)
subForest _ Empty = []
subForest kf (Val _ t) = subForest kf (norm t)
subForest _ _ = error "StringMap.Base.subForest: Pattern match failure"
prefixFindWithKeyBF :: Key -> StringMap a -> [(Key, a)]
prefixFindWithKeyBF k = fmap (first (k ++)) . toListShortestFirst . lookupPx' k
instance Functor StringMap where
fmap = map
instance F.Foldable StringMap where
foldr = fold
instance T.Traversable StringMap where
traverse _ (Empty) = pure Empty
traverse f (Val v t) = Val <$> f v <*> T.traverse f t
traverse f (Branch c s n) = Branch c <$> T.traverse f s <*> T.traverse f n
traverse f (Leaf v) = Leaf <$> f v
traverse f (Last c s) = Last c <$> T.traverse f s
traverse f (LsSeq ks s) = LsSeq ks <$> T.traverse f s
traverse f (BrSeq ks s n) = BrSeq ks <$> T.traverse f s <*> T.traverse f n
traverse f (LsSeL ks v) = LsSeL ks <$> f v
traverse f (BrSeL ks v n) = BrSeL ks <$> f v <*> T.traverse f n
traverse f (LsVal k v) = LsVal k <$> f v
traverse f (BrVal k v n) = BrVal k <$> f v <*> T.traverse f n
instance Read a => Read (StringMap a) where
readsPrec p = readParen (p > 10) $
\ r -> do
("fromList",s) <- lex r
(xs,t) <- reads s
return (fromList xs,t)
instance NFData a => NFData (StringMap a) where
rnf (Empty) = ()
rnf (Val v t) = rnf v `seq` rnf t
rnf (Branch _c s n) = rnf s `seq` rnf n
rnf (Leaf v) = rnf v
rnf (Last _c s) = rnf s
rnf (LsSeq _ks s) = rnf s
rnf (BrSeq _ks s n) = rnf s `seq` rnf n
rnf (LsSeL _ks v) = rnf v
rnf (BrSeL _ks v n) = rnf v `seq` rnf n
rnf (LsVal k v) = rnf k `seq` rnf v
rnf (BrVal k v n) = rnf k `seq` rnf v `seq` rnf n
instance (Binary a) => Binary (StringMap a) where
put (Empty) = put (0::Word8)
put (Val v t) = put (1::Word8) >> put v >> put t
put (Branch c s n) = put (2::Word8) >> put c >> put s >> put n
put (Leaf v) = put (3::Word8) >> put v
put (Last c s) = put (4::Word8) >> put c >> put s
put (LsSeq k s) = put (5::Word8) >> put (toKey k) >> put s
put (BrSeq k s n) = put (6::Word8) >> put (toKey k) >> put s >> put n
put (LsSeL k v) = put (7::Word8) >> put (toKey k) >> put v
put (BrSeL k v n) = put (8::Word8) >> put (toKey k) >> put v >> put n
put (LsVal k v) = put (9::Word8) >> put k >> put v
put (BrVal k v n) = put (10::Word8) >> put k >> put v >> put n
get = do
!tag <- getWord8
case tag of
0 -> return Empty
1 -> do
!v <- get
!t <- get
return $! Val v t
2 -> do
!c <- get
!s <- get
!n <- get
return $! Branch c s n
3 -> do
!v <- get
return $! Leaf v
4 -> do
!c <- get
!s <- get
return $! Last c s
5 -> do
!k <- get
!s <- get
return $! LsSeq (fromKey k) s
6 -> do
!k <- get
!s <- get
!n <- get
return $! BrSeq (fromKey k) s n
7 -> do
!k <- get
!v <- get
return $! LsSeL (fromKey k) v
8 -> do
!k <- get
!v <- get
!n <- get
return $! BrSeL (fromKey k) v n
9 -> do
!k <- get
!v <- get
return $! LsVal k v
10 -> do
!k <- get
!v <- get
!n <- get
return $! BrVal k v n
_ -> fail "StringMap.get: error while decoding StringMap"
#if sizeable
instance Sizeable Key1 where
dataOf x
= case x of
Nil -> dataOfSingleton
(S1 _) -> dataOfChar
(S2 _ _) -> 2 .*. dataOfChar
(S3 _ _ _) -> 3 .*. dataOfChar
(S4 _ _ _ _) -> 4 .*. dataOfChar
(C1 _ _k) -> dataOfChar <> dataOfPtr
(C2 _ _ _k) -> 2 .*. dataOfChar <> dataOfPtr
(C3 _ _ _ _k) -> 3 .*. dataOfChar <> dataOfPtr
(C4 _ _ _ _ _k) -> 4 .*. dataOfChar <> dataOfPtr
statsOf x
= case x of
Nil -> constrStats "Nil" x
(S1 _) -> constrStats "S1" x
(S2 _ _) -> constrStats "S2" x
(S3 _ _ _) -> constrStats "S3" x
(S4 _ _ _ _) -> constrStats "S4" x
(C1 _ k1) -> constrStats "C1" x <> statsOf k1
(C2 _ _ k1) -> constrStats "C2" x <> statsOf k1
(C3 _ _ _ k1) -> constrStats "C3" x <> statsOf k1
(C4 _ _ _ _ k1) -> constrStats "C4" x <> statsOf k1
instance (Sizeable v, Typeable v) => Sizeable (StringMap v) where
dataOf x
= case x of
Empty -> dataOfSingleton
(Val _v _t) -> 2 .*. dataOfPtr
(Branch _ _c _n) -> dataOfChar <> 2 .*. dataOfPtr
(Leaf _v ) -> dataOfPtr
(Last _ _c ) -> dataOfChar <> dataOfPtr
(LsSeq _k _c ) -> 2 .*. dataOfPtr
(BrSeq _k _c _n) -> 3 .*. dataOfPtr
(LsSeL _k _v ) -> 2 .*. dataOfPtr
(BrSeL _k _v _n) -> 3 .*. dataOfPtr
(BrVal _ _v _n) -> dataOfChar <> 2 .*. dataOfPtr
(LsVal _ _v ) -> dataOfChar <> dataOfPtr
statsOf x
= case x of
Empty -> constrStats "Empty" x
(Val v t) -> constrStats "Val" x <> statsOf v <> statsOf t
(Branch _ c n) -> constrStats "Branch" x <> statsOf c <> statsOf n
(Leaf v) -> constrStats "Leaf" x <> statsOf v
(Last _ c) -> constrStats "Last" x <> statsOf c
(LsSeq k c) -> constrStats "LsSeq" x <> statsOf k <> statsOf c
(BrSeq k c n) -> constrStats "BrSeq" x <> statsOf k <> statsOf c <> statsOf n
(LsSeL k v) -> constrStats "LsSeL" x <> statsOf k <> statsOf v
(BrSeL k v n) -> constrStats "BrSeL" x <> statsOf k <> statsOf v <> statsOf n
(BrVal _ v n) -> constrStats "BrVal" x <> statsOf v <> statsOf n
(LsVal _ v) -> constrStats "LsVal" x <> statsOf v
#endif