module Data.TrieMap.MultiRec.UnionMap () where
import Data.TrieMap.MultiRec.Class
import Data.TrieMap.TrieKey
import Control.Applicative
import Control.Monad
import Generics.MultiRec
import Prelude hiding (foldr)
data UnionMap (phi :: * -> *) f g (r :: * -> *) ix a = HTrieMapT phi f r ix a :&: HTrieMapT phi g r ix a
type instance HTrieMapT phi (f :+: g) = UnionMap phi f g
instance (HTrieKeyT phi f (HTrieMapT phi f), HTrieKeyT phi g (HTrieMapT phi g)) => HTrieKeyT phi (f :+: g) (UnionMap phi f g) where
emptyH = liftM2 (:&:) emptyH emptyH
nullH pf (m1 :&: m2) = nullH pf m1 && nullH pf m2
sizeH pf s (m1 :&: m2) = sizeH pf s m1 + sizeH pf s m2
lookupH pf k (m1 :&: m2)
| L k <- k = lookupH pf k m1
| R k <- k = lookupH pf k m2
lookupIxH pf s k (m1 :&: m2)
| L k <- k = case onKey L (lookupIxH pf s k m1) of
(lb, x, ub) -> (lb, x, ub <|> ((onKeyA R . onIndexA (+ sizeH pf s m1)) <$> getMin pf s m2))
| R k <- k = case onIndex (sizeH pf s m1 +) (onKey R (lookupIxH pf s k m2)) of
(lb, x, ub) -> ((onKeyA L <$> getMax pf s m1) <|> lb, x, ub)
where getMin pf s m = aboutH pf (\ k a -> return $ Asc 0 k a) m
getMax pf s m = aboutH pf (\ k a -> return $ Asc (sizeH pf s m s a) k a) m
assocAtH pf s i (m1 :&: m2)
| i < s1 = case onKey L (assocAtH pf s i m1) of
(lb, x, ub) -> (lb, x, ub <|> ((onKeyA R . onIndexA (+ s1)) <$> getMin pf s m2))
| otherwise = case onKey R (onIndex (s1 +) (assocAtH pf s (i s1) m2)) of
(lb, x, ub) -> ((onKeyA L <$> getMax pf s m1) <|> lb, x, ub)
where getMin pf s m = aboutH pf (\ k a -> return $ Asc 0 k a) m
getMax pf s m = aboutH pf (\ k a -> return $ Asc (sizeH pf s m s a) k a) m
s1 = sizeH pf s m1
alterH pf s f k (m1 :&: m2)
| L k <- k = alterH pf s f k m1 :&: m2
| R k <- k = m1 :&: alterH pf s f k m2
alterLookupH pf s f k (m1 :&: m2)
| L k <- k = fmap (:&: m2) (alterLookupH pf s f k m1)
| R k <- k = fmap (m1 :&:) (alterLookupH pf s f k m2)
traverseWithKeyH pf s f (m1 :&: m2)
= (:&:) <$> traverseWithKeyH pf s (f . L) m1 <*> traverseWithKeyH pf s (f . R) m2
foldWithKeyH pf f (m1 :&: m2)
= foldWithKeyH pf (f . L) m1 . foldWithKeyH pf (f . R) m2
foldlWithKeyH pf f (m1 :&: m2)
= foldlWithKeyH pf (f . R) m2 . foldlWithKeyH pf (f . L) m1
mapEitherH pf s1 s2 f (m1 :&: m2) = case (mapEitherH pf s1 s2 (f . L) m1, mapEitherH pf s1 s2 (f . R) m2) of
((m1L, m1R), (m2L, m2R)) -> (m1L :&: m2L, m1R :&: m2R)
splitLookupH pf s f k0 (m1 :&: m2)
| L k <- k0, (m1L, x, m1R) <- splitLookupH pf s f k m1
= (m1L :&: emptyH pf, x, m1R :&: m2)
| R k <- k0, (m2L, x, m2R) <- splitLookupH pf s f k m2
= (m1 :&: m2L, x, emptyH pf :&: m2R)
unionH pf s f (m11 :&: m12) (m21 :&: m22)
= unionH pf s (f . L) m11 m21 :&: unionH pf s (f . R) m12 m22
isectH pf s f (m11 :&: m12) (m21 :&: m22)
= isectH pf s (f . L) m11 m21 :&: isectH pf s (f . R) m12 m22
diffH pf s f (m11 :&: m12) (m21 :&: m22)
= diffH pf s (f . L) m11 m21 :&: diffH pf s (f . R) m12 m22
extractH pf s f (m1 :&: m2) = fmap (:&: m2) <$> extractH pf s (f . L) m1 <|>
fmap (m1 :&:) <$> extractH pf s (f . R) m2
isSubmapH pf (<=) (m11 :&: m12) (m21 :&: m22)
= isSubmapH pf (<=) m11 m21 && isSubmapH pf (<=) m12 m22
fromListH pf s f xs = case breakEither xs of
(ys, zs) -> fromListH pf s (f . L) ys :&: fromListH pf s (f . R) zs
fromAscListH pf s f xs = case breakEither xs of
(ys, zs) -> fromAscListH pf s (f . L) ys :&: fromAscListH pf s (f . R) zs
fromDistAscListH pf s xs = case breakEither xs of
(ys, zs) -> fromDistAscListH pf s ys :&: fromDistAscListH pf s zs