module Data.TrieMap.MultiRec.ProdMap where
import Data.TrieMap.MultiRec.Class
import Data.TrieMap.MultiRec.Eq
import Data.TrieMap.MultiRec.Sized
import Data.TrieMap.Applicative
import Data.TrieMap.TrieKey
import Control.Applicative
import Control.Arrow
import Data.Maybe
import Data.Foldable
import Data.Sequence ((|>))
import qualified Data.Sequence as Seq
import Generics.MultiRec
newtype ProdMap (phi :: * -> *) m1 (m2 :: (* -> *) -> (* -> *) -> * -> *) (r :: * -> *) (a :: * -> *) ix = PMap (m1 r (m2 r a) ix)
type instance HTrieMapT phi (f :*: g) = ProdMap phi (HTrieMapT phi f) (HTrieMapT phi g)
type instance HTrieMap phi ((f :*: g) r) = HTrieMapT phi (f :*: g) r
instance (HTrieKeyT phi f m1, m1 ~ HTrieMapT phi f, HTrieKeyT phi g m2, m2 ~ HTrieMapT phi g) =>
HTrieKeyT phi (f :*: g) (ProdMap phi m1 m2) where
emptyT = PMap . emptyT
nullT pf (PMap m) = nullT pf m
sizeT s (PMap m) = sizeT (sizeT s) m
lookupT pf (a :*: b) (PMap m) = lookupT pf a m >>= lookupT pf b
lookupIxT pf s (a :*: b) (PMap m) = do
(iA, m') <- lookupIxT pf (sizeT s) a m
(iB, v) <- lookupIxT pf s b m'
return (iA + iB, v)
assocAtT pf s i (PMap m) = case assocAtT pf (sizeT s) i m of
(iA, a, m') -> case assocAtT pf s (i iA) m' of
(iB, b, v) -> (iA + iB, a :*: b, v)
updateAtT pf s f i (PMap m) = PMap (updateAtT pf (sizeT s) g i m) where
g iA a = guardNullT pf . updateAtT pf s (\ iB b -> f (iA + iB) (a :*: b)) (i iA)
alterT pf s f (a :*: b) (PMap m) = PMap (alterT pf (sizeT s) (guardNullT pf . g) a m) where
g = alterT pf s f b . fromMaybe (emptyT pf)
traverseWithKeyT pf s f (PMap m) =
PMap <$> traverseWithKeyT pf (sizeT s) (\ a -> traverseWithKeyT pf s (\ b -> f (a :*: b))) m
foldWithKeyT pf f (PMap m) =
foldWithKeyT pf (\ a -> foldWithKeyT pf (\ b -> f (a :*: b))) m
foldlWithKeyT pf f (PMap m) =
foldlWithKeyT pf (\ a -> flip (foldlWithKeyT pf (\ b -> f (a :*: b)))) m
mapEitherT pf s1 s2 f (PMap m) = (PMap *** PMap) (mapEitherT pf (sizeT s1) (sizeT s2) g m) where
g a = (guardNullT pf *** guardNullT pf) . mapEitherT pf s1 s2 (\ b -> f (a :*: b))
splitLookupT pf s f (a :*: b) (PMap m) = PMap `sides` splitLookupT pf (sizeT s) g a m where
g = sides (guardNullT pf) . splitLookupT pf s f b
unionT pf s f (PMap m1) (PMap m2) = PMap (unionT pf (sizeT s) g m1 m2) where
g a = guardNullT pf .: unionT pf s (\ b -> f (a :*: b))
isectT pf s f (PMap m1) (PMap m2) = PMap (isectT pf (sizeT s) g m1 m2) where
g a = guardNullT pf .: isectT pf s (\ b -> f (a :*: b))
diffT pf s f (PMap m1) (PMap m2) = PMap (diffT pf (sizeT s) g m1 m2) where
g a = guardNullT pf .: diffT pf s (\ b -> f (a :*: b))
extractMinT pf s (PMap m) = do
((a, m1), m') <- extractMinT pf (sizeT s) m
((b, v), m1') <- extractMinT pf s m1
return ((a :*: b, v), PMap (maybe m' (\ m1' -> alterMinT pf (sizeT s) (\ _ _ -> Just m1') m) (guardNullT pf m1')))
extractMaxT pf s (PMap m) = do
((a, m1), m') <- extractMaxT pf (sizeT s) m
((b, v), m1') <- extractMaxT pf s m1
return ((a :*: b, v), PMap (maybe m' (\ m1' -> alterMaxT pf (sizeT s) (\ _ _ -> Just m1') m) (guardNullT pf m1')))
alterMinT pf s f (PMap m) = PMap (alterMinT pf (sizeT s) g m) where
g a = guardNullT pf . alterMinT pf s (\ b -> f (a :*: b))
alterMaxT pf s f (PMap m) = PMap (alterMaxT pf (sizeT s) g m) where
g a = guardNullT pf . alterMaxT pf s (\ b -> f (a :*: b))
isSubmapT pf (<=) (PMap m1) (PMap m2) = isSubmapT pf (isSubmapT pf (<=)) m1 m2
fromListT pf s f xs = PMap (mapWithKeyT pf (sizeT s) (\ a -> fromListT pf s (\ b -> f (a :*: b)) . unK0)
(fromListT pf (const 1) (\ _ (K0 xs) (K0 ys) -> K0 (xs ++ ys))
[(a, K0 ts) | (a, ts) <- breakFst pf xs]))
fromAscListT pf s f xs = PMap (fromDistAscListT pf (sizeT s)
[(a, fromAscListT pf s (\ b -> f (a :*: b)) ts) | (a, ts) <- breakFst pf xs])
fromDistAscListT pf s xs = PMap (fromDistAscListT pf (sizeT s)
[(a, fromDistAscListT pf s ts) | (a, ts) <- breakFst pf xs])
breakFst :: (HEq phi f, HEq0 phi r) => phi ix -> [((f :*: g) r ix, a ix)] -> [(f r ix, [(g r ix, a ix)])]
breakFst pf [] = []
breakFst pf ((a :*: b, x):xs) = breakFst' a (Seq.singleton (b, x)) xs where
breakFst' a0 ts ((a :*: b, x):xs)
| heqT pf a0 a = breakFst' a0 (ts |> (b, x)) xs
| otherwise = (a0, toList ts):breakFst' a (Seq.singleton (b,x)) xs
breakFst' a ts [] = [(a, toList ts)]
instance (HTrieKeyT phi f m1, m1 ~ HTrieMapT phi f, HTrieKeyT phi g m2, m2 ~ HTrieMapT phi g,
HTrieKey phi r (HTrieMap phi r)) => HTrieKey phi ((f :*: g) r) (ProdMap phi m1 m2 r) where
emptyH = emptyT
nullH = nullT
sizeH = sizeT
lookupH = lookupT
lookupIxH = lookupIxT
assocAtH = assocAtT
updateAtH = updateAtT
alterH = alterT
traverseWithKeyH = traverseWithKeyT
foldWithKeyH = foldWithKeyT
foldlWithKeyH = foldlWithKeyT
mapEitherH = mapEitherT
splitLookupH = splitLookupT
unionH = unionT
isectH = isectT
diffH = diffT
alterMinH = alterMinT
alterMaxH = alterMaxT
extractMinH = extractMinT
extractMaxH = extractMaxT
isSubmapH = isSubmapT
fromListH = fromListT
fromAscListH = fromAscListT
fromDistAscListH = fromDistAscListT