module Data.TrieMap.Regular.ProdMap() where
import Data.TrieMap.Regular.Class
import Data.TrieMap.Regular.Base
import Data.TrieMap.Regular.Eq
import Data.TrieMap.TrieKey
import Data.TrieMap.Applicative
import Data.TrieMap.Sized
import Control.Applicative
import Control.Arrow
import Data.Maybe
import Data.Monoid
import Data.Sequence (Seq, (|>))
import qualified Data.Sequence as Seq
import Data.Foldable
newtype PMap m1 (m2 :: * -> * -> *) k a = PMap (m1 k (m2 k a))
type instance TrieMapT (f :*: g) = PMap (TrieMapT f) (TrieMapT g)
type instance TrieMap ((f :*: g) r) = TrieMapT (f :*: g) r
lastIx :: (TrieKeyT f (TrieMapT f), TrieKey k (TrieMap k)) => Sized a -> TrieMapT f k a -> Int
lastIx s m = fromMaybe (sizeT s m) (getLast (aboutT (\ _ a -> return $ sizeT s m s a) m))
instance (TrieKeyT f m1, TrieKeyT g m2, TrieKey k (TrieMap k)) =>
TrieKey ((f :*: g) k) (PMap m1 m2 k) 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 (TrieKeyT f m1, TrieKeyT g m2) => TrieKeyT (f :*: g) (PMap m1 m2) where
emptyT = PMap emptyT
nullT (PMap m) = nullT m
sizeT s (PMap m) = sizeT (sizeT s) m
lookupT (a :*: b) (PMap m) = lookupT a m >>= lookupT b
lookupIxT s (a :*: b) (PMap m) = case lookupIxT (sizeT s) a m of
(lb, x, ub) -> let lookupX = do Asc i' a' m' <- x
let (lb', x', ub') = lookupIxT s b m'
let f = onKeyA (a' :*:) . onIndexA (i' +)
return (f <$> lb', f <$> x', f <$> ub')
in ((do Asc iL aL mL <- lb
fmap (onKeyA (aL :*:) . onIndexA (iL +)) (getMax s mL)) <|>
(do (lb', _, _) <- Last lookupX
lb'),
(do (_, x', _) <- lookupX
x'),
(do (_, _, ub') <- First lookupX
ub') <|>
(do Asc iR aR mR <- ub
fmap (onKeyA (aR :*:) . onIndexA (iR +)) (getMin s mR)))
where getMin s m = aboutT (\ k a -> return (Asc 0 k a)) m
getMax s m = aboutT (\ k a -> return (Asc (sizeT s m s a) k a)) m
assocAtT s i (PMap m) = case assocAtT (sizeT s) i m of
(lb, x, ub) -> let lookupX = do Asc i' a' m' <- x
let (lb', x', ub') = assocAtT s (i i') m'
let f = onKeyA (a' :*:) . onIndexA (i' +)
return (f <$> lb', f <$> x', f <$> ub')
in ((do Asc iL aL mL <- lb
fmap (onKeyA (aL :*:) . onIndexA (iL +)) (getMax mL)) <|>
(do (lb', _, _) <- Last lookupX
lb'),
(do (_, x', _) <- lookupX
x'),
(do (_, _, ub') <- First lookupX
ub') <|>
(do Asc iR aR mR <- ub
fmap (onKeyA (aR :*:) . onIndexA (iR +)) (getMin mR)))
where getMin m = aboutT (\ k a -> return (Asc 0 k a)) m
getMax m = aboutT (\ k a -> return (Asc (sizeT s m s a) k a)) m
alterT s f (a :*: b) (PMap m) = PMap (alterT (sizeT s) g a m) where
g = guardNullT . alterT s f b . fromMaybe emptyT
alterLookupT s f (a :*: b) (PMap m) = PMap <$> alterLookupT (sizeT s) g a m where
g = fmap guardNullT . alterLookupT s f b . fromMaybe emptyT
traverseWithKeyT s f (PMap m) = PMap <$> traverseWithKeyT (sizeT s) g m where
g a = traverseWithKeyT s (\ b -> f (a :*: b))
foldWithKeyT f (PMap m) = foldWithKeyT g m where
g a = foldWithKeyT (\ b -> f (a :*: b))
foldlWithKeyT f (PMap m) = foldlWithKeyT g m where
g a z m = foldlWithKeyT (\ b -> f (a :*: b)) m z
mapEitherT s1 s2 f (PMap m) = (PMap *** PMap) (mapEitherT (sizeT s1) (sizeT s2) g m) where
g a = (guardNullT *** guardNullT) . mapEitherT s1 s2 (\ b -> f (a :*: b))
splitLookupT s f (a :*: b) (PMap m) = PMap `sides` splitLookupT (sizeT s) g a m where
g = sides guardNullT . splitLookupT s f b
unionT s f (PMap m1) (PMap m2) = PMap (unionT (sizeT s) (\ a -> guardNullT .: unionT s (\ b -> f (a :*: b))) m1 m2)
isectT s f (PMap m1) (PMap m2) = PMap (isectT (sizeT s) (\ a -> guardNullT .: isectT s (\ b -> f (a :*: b))) m1 m2)
diffT s f (PMap m1) (PMap m2) = PMap (diffT (sizeT s) (\ a -> guardNullT .: diffT s (\ b -> f (a :*: b))) m1 m2)
extractT s f (PMap m) = fmap PMap <$> extractT (sizeT s) g m where
g a = fmap guardNullT <.> extractT s (\ b -> f (a :*: b))
isSubmapT (<=) (PMap m1) (PMap m2) = isSubmapT (isSubmapT (<=)) m1 m2
fromListT s f xs = PMap (mapWithKeyT (sizeT s) (\ a -> fromListT s (\ b -> f (a :*: b)))
(fromListT (const 1) (const (++)) (breakFst xs)))
fromAscListT s f xs = PMap (fromDistAscListT (sizeT s)
[(a, fromAscListT s (\ b -> f (a :*: b)) ys) | (a, ys) <- breakFst xs])
breakFst :: (EqT f, Eq k) => [((f :*: g) k, a)] -> [(f k, [(g k, a)])]
breakFst [] = []
breakFst ((a :*: b, v):xs) = breakFst' a (Seq.singleton (b, v)) xs where
breakFst' a vs ((a' :*: b', v):xs)
| a `eqT` a' = breakFst' a (vs |> (b', v)) xs
| otherwise = (a, toList vs):breakFst' a' (Seq.singleton (b', v)) xs
breakFst' a vs [] = [(a, toList vs)]