{-# LANGUAGE IncoherentInstances, PatternGuards, MultiParamTypeClasses, UndecidableInstances #-} module TrieMap.RadixTrie where import Control.Applicative import Data.Maybe import Data.Monoid import Data.Foldable import Data.Sequence (Seq, (|>)) import qualified Data.Sequence as Seq import Data.Traversable import TrieMap.Algebraic import TrieMap.Applicative import TrieMap.MapTypes import TrieMap.TrieAlgebraic import Prelude hiding (foldr) instance Sized (Edge k m a) where getSize (Edge s _ _ _) = s instance TrieKeyT [] RadixTrie where compareKeyT (a:as) (b:bs) = compareKey a b `mappend` compareKeyT as bs compareKeyT [] (_:_) = LT compareKeyT (_:_) [] = GT compareKeyT [] [] = EQ emptyT = Radix Nothing nullT (Radix m) = isNothing m sizeT (Radix m) = getSize m getSingleT (Radix m) = m >>= getSingleEdge guardNullT (Radix m) = m >>= guardNullEdge >>= return . Radix . Just alterLookupT f ks (Radix Nothing) = (Radix . single ks) <$> f Nothing alterLookupT f ks (Radix (Just e)) = Radix <$> alterLookupEdge f ks e lookupT ks (Radix m) = m >>= lookupEdge ks foldWithKeyT f z (Radix m) = foldr (foldEdge f) z m mapAppT f (Radix m) = Radix <$> traverse (mapAppEdge f) m mapMaybeT f (Radix m) = Radix (m >>= mapMaybeEdge f) mapEitherT f (Radix m) = radBoth (maybe (Nothing, Nothing) (mapEitherEdge f) m) where radBoth (e1, e2) = (Radix e1, Radix e2) fromDistAscListT = fromAscListT (\ _ x _ -> x) fromAscListT _ [] = Radix Nothing fromAscListT f (x:xs) = Radix (Just (groupAscHeads' f x xs)) fromListT f xs = Radix (groupHeads f xs) splitLookupT _ _ (Radix Nothing) = (emptyT, Nothing, emptyT) splitLookupT f k (Radix (Just e)) = case splitLookupEdge f k e of (eL, ans, eR) -> (Radix eL, ans, Radix eR) isSubmapT (<=) (Radix m1) (Radix m2) = isSubmapAlg (isSubEdge (<=)) m1 m2 getMinT (Radix m) = fmap (Radix <$>) (m >>= getMinEdge) getMaxT (Radix m) = fmap (Radix <$>) (m >>= getMaxEdge) updateMinT _ (Radix Nothing) = (False, Radix Nothing) updateMinT f (Radix (Just e)) = Radix <$> updateMinEdge f e updateMaxT _ (Radix Nothing) = (False, Radix Nothing) updateMaxT f (Radix (Just e)) = Radix <$> updateMaxEdge f e unionT f (Radix m1) (Radix m2) = Radix (unionMaybe (unionEdge f) m1 m2) intersectT f (Radix m1) (Radix m2) = Radix (intersectMaybe (intersectEdge f) m1 m2) differenceT f (Radix m1) (Radix m2) = Radix (differenceMaybe (differenceEdge f) m1 m2) instance TrieKey k m => TrieKey [k] (RadixTrie k m) where compareKey = compareKeyT emptyAlg = emptyT nullAlg = nullT getSingleAlg = getSingleT guardNullAlg = guardNullT sizeAlg = sizeT lookupAlg = lookupT alterLookupAlg = alterLookupT mapAppAlg = mapAppT mapMaybeAlg = mapMaybeT mapEitherAlg = mapEitherT foldWithKeyAlg = foldWithKeyT unionMaybeAlg = unionT intersectAlg = intersectT differenceAlg = differenceT getMinAlg = getMinT getMaxAlg = getMaxT updateMinAlg = updateMinT updateMaxAlg = updateMaxT isSubmapAlg = isSubmapT splitLookupAlg = splitLookupT single :: (Sized a, TrieKey k m) => [k] -> Maybe a -> MEdge k m a single ks = fmap (\ v -> Edge (getSize v) ks (Just v) emptyAlg) edge :: (Sized a, TrieKey k m) => [k] -> Maybe a -> m (Edge k m a) -> Edge k m a edge ks v ts = Edge (getSize v + getSize ts) ks v ts getSingleEdge :: TrieKey k m => Edge k m a -> Maybe ([k], a) getSingleEdge (Edge _ ks (Just v) ts) | nullAlg ts = Just (ks, v) getSingleEdge (Edge _ ks Nothing ts) = do (l, e') <- getSingleAlg ts (ls, v) <- getSingleEdge e' return (ks ++ l:ls, v) getSingleEdge _ = Nothing guardNullEdge :: TrieKey k m => Edge k m a -> MEdge k m a guardNullEdge (Edge s ks Nothing ts) | nullAlg ts = Nothing | Just (l, Edge _ ls v ts') <- getSingleAlg ts = Just (Edge s (ks ++ l:ls) v ts') guardNullEdge e = Just e alterLookupEdge :: (Eq k, TrieKey k m, Sized a) => (Maybe a -> (b, Maybe a)) -> [k] -> Edge k m a -> (b, MEdge k m a) alterLookupEdge f ks0 e@(Edge s ls0 v0 ts) = procEdge 0 ks0 ls0 where procEdge i _ _ | i `seq` False = undefined procEdge i (k:ks) (l:ls) | k == l = procEdge (i+1) ks ls | otherwise = breakEdge <$> f Nothing where breakEdge Nothing = Just e breakEdge (Just v) = let sV = getSize v in Just (Edge (sV + s) (take i ls0) Nothing (fromListAlg (\ _ v _ -> v) [(k, Edge sV ks (Just v) emptyAlg), (l, Edge s ls v0 ts)])) procEdge _ [] (l:ls) = splitEdge <$> f Nothing where splitEdge Nothing = Just e splitEdge (Just v) = let sV = getSize v in Just (Edge (sV + s) ks0 (Just v) (singletonAlg l (Edge s ls v0 ts))) procEdge _(k:ks) [] = (guardNullEdge . edge ls0 v0) <$> alterLookupAlg g k ts where g Nothing = fmap (\ v -> Edge (getSize v) ks (Just v) emptyAlg) <$> f Nothing g (Just e) = alterLookupEdge f ks e procEdge _ [] [] = fmap (\ v -> guardNullEdge $ edge ls0 v ts) (f v0) lookupEdge :: (Eq k, TrieKey k m) => [k] -> Edge k m a -> Maybe a lookupEdge ks (Edge _ ls v ts) = procEdge ks ls where procEdge (k:ks) (l:ls) | k == l = procEdge ks ls procEdge (k:ks) [] = lookupAlg k ts >>= lookupEdge ks procEdge [] [] = v procEdge _ _ = Nothing foldEdge :: TrieKey k m => ([k] -> a -> b -> b) -> Edge k m a -> b -> b foldEdge f (Edge _ ks v ts) z = foldr (f ks) (foldWithKeyAlg (\ l -> foldEdge (\ ls -> f (ks ++ l:ls))) z ts) v mapAppEdge :: (TrieKey k m, Applicative f, Sized b) => ([k] -> a -> f b) -> Edge k m a -> f (Edge k m b) mapAppEdge f (Edge _ ks v ts) = edge ks <$> traverse (f ks) v <*> mapAppAlg (\ l -> mapAppEdge (\ ls -> f (ks ++ l:ls))) ts mapMaybeEdge :: (TrieKey k m, Sized b) => ([k] -> a -> Maybe b) -> Edge k m a -> MEdge k m b mapMaybeEdge f (Edge _ ks v ts) = guardNullEdge (edge ks (v >>= f ks) (mapMaybeAlg (\ l -> mapMaybeEdge (\ ls -> f (ks ++ l:ls))) ts)) mapEitherEdge :: (TrieKey k m, Sized b, Sized c) => ([k] -> a -> (Maybe b, Maybe c)) -> Edge k m a -> (MEdge k m b, MEdge k m c) mapEitherEdge f (Edge _ ks v ts) = guardBoth (edge ks vL tsL, edge ks vR tsR) where (vL, vR) = maybe (Nothing, Nothing) (f ks) v ts' = mapEitherAlg (\ l -> mapEitherEdge (\ ls -> f (ks ++ l:ls))) ts (tsL, tsR) = mapEitherAlg (\ l -> mapEitherEdge (\ ls -> f (ks ++ l:ls))) ts guardBoth (e1, e2) = (guardNullEdge e1, guardNullEdge e2) groupAscHeads' :: (Eq k, TrieKey k m, Sized a) => ([k] -> a -> a -> a) -> ([k], a) -> [([k], a)] -> Edge k m a groupAscHeads' f (ks, v) [] = Edge (getSize v) ks (Just v) emptyAlg groupAscHeads' f x xs = group0 Nothing (x:xs) where group0 v0 (([], v):xs) = group0 (Just (maybe v (f [] v) v0)) xs group0 (Just v0) [] = Edge (getSize v0) [] (Just v0) emptyAlg group0 v0 ((k:ks, v):xs) = group1 Seq.empty k (ks, v) Seq.empty xs where group1 ts k vk vs ((l:ls, v):xs) | k == l = group1 ts k vk (vs |> (ls, v)) xs | otherwise = group1 (ts |> (k, groupAscHeads' (f . (k:)) vk (toList vs))) l (ls, v) Seq.empty xs group1 ts k v vs [] | Nothing <- v0, Seq.null ts, Edge s xs vX tsX <- groupAscHeads' (f . (k:)) v (toList vs) = Edge s (k:xs) vX tsX | otherwise = edge [] v0 (fromDistAscListAlg (toList ts ++ [(k, groupAscHeads' (f . (k:)) v (toList vs))])) groupHeads :: (Eq k, TrieKey k m, Sized a) => ([k] -> a -> a -> a) -> [([k], a)] -> MEdge k m a groupHeads _ [] = Nothing groupHeads f xs = guardNullEdge $ edge [] v0 (mapMaybeAlg (\ k (Elem xs) -> groupHeads (f . (k:)) xs) $ fromListAlg (\ _ (Elem x) (Elem y) -> Elem (x ++ y)) [(k, Elem [(ks, v)]) | (k, ks, v) <- ts]) where (v0, ts) = let proc ([], v) (v0, ts) = (Just (maybe v (f [] v) v0), ts) proc (k:ks, v) (v0, ts) = (v0, (k, ks, v):ts) in foldr proc (Nothing, []) xs mapEdge :: (Sized b, TrieKey k m) => ([k] -> a -> b) -> Edge k m a -> Edge k m b mapEdge f (Edge _ ks v ts) = edge ks (fmap (f ks) v) (mapWithKeyAlg (\ l -> mapEdge (\ ls -> f (ks ++ l:ls))) ts) splitLookupEdge :: (Sized a, TrieKey k m) => (a -> (Maybe a, Maybe b, Maybe a)) -> [k] -> Edge k m a -> (MEdge k m a, Maybe b, MEdge k m a) splitLookupEdge f ks e@(Edge s ls v ts) = procEdge ks ls where procEdge (k:ks) (l:ls) = case compareKey k l of LT -> (Nothing, Nothing, Just e) GT -> (Just e, Nothing, Nothing) EQ -> procEdge ks ls procEdge (k:ks) [] = case splitLookupAlg g k ts of (tsL, ans, tsR) -> (guardNullEdge (edge ls v tsL), ans, guardNullEdge (edge ls Nothing tsR)) where g = splitLookupEdge f ks procEdge [] (l:ls) = (Nothing, Nothing, Just e) procEdge [] [] = case v of Nothing -> (Nothing, Nothing, Just e) Just v -> case f v of (vL, ans, vR) -> (single ls vL, ans, guardNullEdge (edge ls vR ts)) isSubEdge :: (TrieKey k m, Sized a, Sized b) => (a -> b -> Bool) -> Edge k m a -> Edge k m b -> Bool isSubEdge (<=) (Edge sK ks vK tsK) (Edge _ ls vL tsL) = procEdge ks ls where procEdge (k:ks) (l:ls) | k == l = procEdge ks ls procEdge (k:ks) [] | Just e' <- lookupAlg k tsL = isSubEdge (<=) (Edge sK ks vK tsK) e' procEdge [] [] = isSubmapAlg (<=) vK vL && isSubmapAlg (isSubEdge (<=)) tsK tsL getMinEdge :: (TrieKey k m, Sized a) => Edge k m a -> Maybe (([k], a), MEdge k m a) getMinEdge (Edge s ks (Just v) ts) = Just ((ks, v), guardNullEdge (Edge (s - getSize v) ks Nothing ts)) getMinEdge (Edge _ ks Nothing ts) = do ((l, e'), ts') <- getMinAlg ts ((ls, v), e'') <- getMinEdge e' return ((ks ++ l:ls, v), fmap (edge ks Nothing) (maybe (guardNullAlg ts') (\ e'' -> Just $ snd $ updateMinAlg (\ _ _ -> (False, Just e'')) ts) e'')) getMaxEdge :: (TrieKey k m, Sized a) => Edge k m a -> Maybe (([k], a), MEdge k m a) getMaxEdge (Edge _ ks v0 ts) | nullAlg ts = maybe Nothing (\ v -> Just ((ks, v), Nothing)) v0 | otherwise = do ((l, e'), ts') <- getMaxAlg ts ((ls, v), e'') <- getMaxEdge e' return ((ks ++ l:ls, v), fmap (edge ks Nothing) (maybe (guardNullAlg ts') (\ e'' -> Just $ snd $ updateMaxAlg (\ _ _ -> (False, Just e'')) ts) e'')) updateMinEdge :: (TrieKey k m, Sized a) => ([k] -> a -> (Bool, Maybe a)) -> Edge k m a -> (Bool, MEdge k m a) updateMinEdge f (Edge _ ks (Just v) ts) = fmap (\ v -> guardNullEdge (edge ks v ts)) (f ks v) updateMinEdge f (Edge _ ks Nothing ts) = fmap (guardNullEdge . edge ks Nothing) (updateMinAlg g ts) where g l = updateMinEdge (\ ls -> f (ks ++ l:ls)) updateMaxEdge :: (TrieKey k m, Sized a) => ([k] -> a -> (Bool, Maybe a)) -> Edge k m a -> (Bool, MEdge k m a) updateMaxEdge f (Edge _ ks (Just v) ts) | nullAlg ts = fmap (\ v -> guardNullEdge (edge ks v ts)) (f ks v) updateMaxEdge f (Edge _ ks v ts) = fmap (guardNullEdge . edge ks v) (updateMinAlg g ts) where g l = updateMinEdge (\ ls -> f (ks ++ l:ls)) unionEdge :: (TrieKey k m, Sized a) => ([k] -> a -> a -> Maybe a) -> Edge k m a -> Edge k m a -> MEdge k m a unionEdge f (Edge sK ks0 vK tsK) (Edge sL ls0 vL tsL) = procEdge 0 ks0 ls0 where procEdge i _ _ | i `seq` False = undefined procEdge i (k:ks) (l:ls) | k == l = procEdge (i+1) ks ls | otherwise = Just (Edge (sK + sL) (take i ks0) Nothing (insertAlg k (Edge sK ks vK tsK) $ singletonAlg l (Edge sL ls vL tsL))) procEdge _ (k:ks) [] = guardNullEdge $ edge ls0 vL $ alterAlg g k tsL where g Nothing = Just (Edge sK ks vK tsK) g (Just e) = unionEdge (\ ks' -> f (ls0 ++ k:ks')) (Edge sK ks vK tsK) e procEdge _ [] (l:ls) = guardNullEdge $ edge ks0 vK $ alterAlg g l tsK where g Nothing = Just (Edge sL ls vL tsL) g (Just e) = unionEdge (\ ls' -> f (ks0 ++ l:ls')) e (Edge sL ls vL tsL) procEdge _ [] [] = guardNullEdge $ edge ks0 (unionMaybe (f ks0) vK vL) $ unionMaybeAlg (\ x -> unionEdge (\ xs -> f (ks0 ++ x:xs))) tsK tsL intersectEdge :: (TrieKey k m, Sized c) => ([k] -> a -> b -> Maybe c) -> Edge k m a -> Edge k m b -> MEdge k m c intersectEdge f (Edge sK ks0 vK tsK) (Edge sL ls0 vL tsL) = procEdge ks0 ls0 where procEdge (k:ks) (l:ls) | k == l = procEdge ks ls | otherwise = Nothing procEdge (k:ks) [] = do e' <- lookupAlg k tsL Edge sX xs vX tsX <- intersectEdge (\ ks' -> f (ls0 ++ k:ks')) (Edge sK ks vK tsK) e' return (Edge sX (ls0 ++ k:xs) vX tsX) procEdge [] (l:ls) = do e' <- lookupAlg l tsK Edge sX xs vX tsX <- intersectEdge (\ ls' -> f (ks0 ++ l:ls')) e' (Edge sL ls vL tsL) return (Edge sX (ks0 ++ l:xs) vX tsX) procEdge [] [] = guardNullEdge $ edge ks0 (intersectMaybe (f ks0) vK vL) (intersectAlg (\ x -> intersectEdge (\ xs -> f (ks0 ++ x:xs))) tsK tsL) differenceEdge :: (TrieKey k m, Sized a) => ([k] -> a -> b -> Maybe a) -> Edge k m a -> Edge k m b -> MEdge k m a differenceEdge f e@(Edge sK ks0 vK tsK) (Edge sL ls0 vL tsL) = procEdge ks0 ls0 where procEdge (k:ks) (l:ls) | k == l = procEdge ks ls procEdge (k:ks) [] | Just e' <- lookupAlg k tsL = do Edge sX xs vX tsX <- differenceEdge (\ ks' -> f (ls0 ++ k:ks')) (Edge sK ks vK tsK) e' return (Edge sX (ls0 ++ k:xs) vX tsX) procEdge [] (l:ls) = guardNullEdge $ edge ks0 vK (alterAlg (>>= g) l tsK) where g e = differenceEdge (\ ls' -> f (ks0 ++ l:ls')) e (Edge sL ls vL tsL) procEdge [] [] = guardNullEdge $ edge ks0 (intersectMaybe (f ks0) vK vL) $ intersectAlg (\ x -> intersectEdge (\ xs -> f (ks0 ++ x:xs))) tsK tsL procEdge _ _ = Just e