module Data.TrieMap.ProdMap () where
import Data.TrieMap.TrieKey
import Data.TrieMap.Applicative
import Data.TrieMap.Regular.Class
import Control.Applicative
import Control.Arrow
import Data.Maybe
import Data.Monoid
import Data.Foldable
import Data.Sequence (Seq, (|>))
import qualified Data.Sequence as Seq
newtype PMap m1 k2 a = PMap (m1 (TrieMap k2 a))
type instance TrieMapT ((,) a) = PMap (TrieMap a)
type instance TrieMap (a, b) = PMap (TrieMap a) b
instance (TrieKey a m, TrieKey b (TrieMap b)) => TrieKey (a, b) (PMap m b) where
emptyM = emptyT
nullM = nullT
lookupM = lookupT
lookupIxM = lookupIxT
assocAtM = assocAtT
alterM = alterT
alterLookupM = alterLookupT
traverseWithKeyM = traverseWithKeyT
foldWithKeyM = foldWithKeyT
foldlWithKeyM = foldlWithKeyT
mapEitherM = mapEitherT
splitLookupM = splitLookupT
unionM = unionT
isectM = isectT
diffM = diffT
extractM = extractT
isSubmapM = isSubmapT
fromListM = fromListT
fromAscListM = fromAscListT
fromDistAscListM = fromDistAscListT
instance TrieKey k1 m1 => TrieKeyT ((,) k1) (PMap m1) where
emptyT = PMap emptyM
nullT (PMap m) = nullM m
sizeT s (PMap m) = sizeM (sizeM s) m
lookupT (k1, k2) (PMap m) = lookupM k1 m >>= lookupM k2
lookupIxT s (a, b) (PMap m) = case lookupIxM (sizeM s) a m of
(lb, x, ub) -> let lookupX = do Asc i1 a' m' <- x
return (onIndex (i1 +) (onKey ((,) a') (lookupIxM s b m')))
in ((do Asc iL aL mL <- lb
aboutM (\ bL v -> return (Asc (iL + sizeM s mL s v) (aL, bL) v)) mL) <|>
(do (lb', _, _) <- Last lookupX
lb'),
(do (_, x', _) <- lookupX
x'),
(do (_, _, ub') <- First lookupX
ub') <|>
(do Asc iU aU mU <- ub
aboutM (\ bU -> return . Asc iU (aU, bU)) mU))
assocAtT s i (PMap m) = case assocAtM (sizeM s) i m of
(lb, x, ub) -> let lookupX = do Asc i1 a' m' <- x
return (onIndex (i1 +) (onKey ((,) a') (assocAtM s (i i1) m')))
in ((do Asc iL aL mL <- lb
aboutM (\ bL v -> return (Asc (iL + sizeM s mL s v) (aL, bL) v)) mL) <|>
(do (lb', _, _) <- Last lookupX
lb'),
(do (_, x', _) <- lookupX
x'),
(do (_, _, ub') <- First lookupX
ub') <|>
(do Asc iU aU mU <- ub
aboutM (\ bU -> return . Asc iU (aU, bU)) mU))
alterT s f (a, b) (PMap m) = PMap (alterM (sizeM s) g a m) where
g = guardNullM . alterM s f b . fromMaybe emptyM
alterLookupT s f (a, b) (PMap m) = PMap <$> alterLookupM (sizeM s) g a m where
g = fmap guardNullM . alterLookupM s f b . fromMaybe emptyM
traverseWithKeyT s f (PMap m) = PMap <$> traverseWithKeyM (sizeM s) (\ a -> traverseWithKeyM s (\ b -> f (a, b))) m
foldWithKeyT f (PMap m) = foldWithKeyM (\ a -> foldWithKeyM (\ b -> f (a, b))) m
foldlWithKeyT f (PMap m) = foldlWithKeyM (\ a -> flip (foldlWithKeyM (\ b -> f (a, b)))) m
mapEitherT s1 s2 f (PMap m) = (PMap *** PMap) (mapEitherM (sizeM s1) (sizeM s2) g m) where
g a = (guardNullM *** guardNullM) . mapEitherM s1 s2 (\ b -> f (a, b))
splitLookupT s f (a, b) (PMap m) = PMap `sides` splitLookupM (sizeM s) g a m where
g = sides guardNullM . splitLookupM s f b
isSubmapT (<=) (PMap m1) (PMap m2) = isSubmapM (isSubmapM (<=)) m1 m2
unionT s f (PMap m1) (PMap m2) = PMap (unionM (sizeM s) (\ a -> guardNullM .: unionM s (\ b -> f (a, b))) m1 m2)
isectT s f (PMap m1) (PMap m2) = PMap (isectM (sizeM s) (\ a -> guardNullM .: isectM s (\ b -> f (a, b))) m1 m2)
diffT s f (PMap m1) (PMap m2) = PMap (diffM (sizeM s) (\ a -> guardNullM .: diffM s (\ b -> f (a, b))) m1 m2)
extractT s f (PMap m) = fmap PMap <$> extractM (sizeM s) g m where
g a = fmap guardNullM <.> extractM s (\ b -> f (a, b))
fromListT s f xs = PMap (mapWithKeyM (sizeM s) (\ a -> fromListM s (\ b -> f (a, b)))
(fromListM (const 1) (const (++)) (breakFst xs)))
fromAscListT s f xs = PMap (fromDistAscListM (sizeM s)
[(a, fromAscListM s (\ b -> f (a, b)) ys) | (a, ys) <- breakFst xs])
breakFst :: Eq k1 => [((k1, k2), a)] -> [(k1, [(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
| otherwise = (a, toList vs):breakFst' a' (Seq.singleton (b', v')) xs
breakFst' a vs [] = [(a, toList vs)]