module Data.TrieMap.ReverseMap (reverse, unreverse) where
import Data.TrieMap.TrieKey
import Data.TrieMap.Modifiers
import Data.TrieMap.Applicative
import Data.TrieMap.Regular.Class
import Data.TrieMap.Regular.TH
import Control.Applicative
import Control.Arrow
import Data.Monoid hiding (Dual)
import Prelude hiding (reverse)
import qualified Data.List as L
newtype ReverseMap k a = RMap (TrieMap k a)
type instance TrieMapT Rev = ReverseMap
type instance TrieMap (Rev k) = ReverseMap k
instance TrieKey k (TrieMap k) => TrieKey (Rev k) (ReverseMap 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 Rev ReverseMap where
emptyT = RMap emptyM
nullT (RMap m) = nullM m
sizeT s (RMap m) = sizeM s m
lookupT (Rev k) (RMap m) = lookupM k m
lookupIxT s (Rev k) (RMap m) = case lookupIxM s k m of
(Last lb, x, First ub) -> onKey Rev (onIndex (sizeM s m 1 ) (Last ub, x, First lb))
assocAtT s i (RMap m) = case assocAtM s (sz 1 i) m of
(Last lb, x, First ub) -> onKey Rev (onIndex (sz ) (Last ub, x, First lb))
where sz = sizeM s m
traverseWithKeyT s f (RMap m) = RMap <$> runDual (traverseWithKeyM s (\ k a -> Dual (f (Rev k) a)) m)
alterT s f (Rev k) (RMap m) = RMap (alterM s f k m)
alterLookupT s f (Rev k) (RMap m) = RMap <$> alterLookupM s f k m
splitLookupT s f (Rev k) (RMap m) = case splitLookupM s f' k m of
(mL, x, mR) -> (RMap mR, x, RMap mL)
where f' x = case f x of
(xL, ans, xR) -> (xR, ans, xL)
mapEitherT s1 s2 f (RMap m) = (RMap *** RMap) (mapEitherM s1 s2 (f . Rev) m)
foldWithKeyT f (RMap m) = foldlWithKeyM (flip . f . Rev) m
foldlWithKeyT f (RMap m) = foldWithKeyM (flip . f . Rev) m
unionT s f (RMap m1) (RMap m2) = RMap (unionM s (f . Rev) m1 m2)
isectT s f (RMap m1) (RMap m2) = RMap (isectM s (f . Rev) m1 m2)
diffT s f (RMap m1) (RMap m2) = RMap (diffM s (f . Rev) m1 m2)
extractT s f (RMap m) = fmap RMap <$> runDual (extractM s (\ k a -> Dual (f (Rev k) a)) m)
isSubmapT (<=) (RMap m1) (RMap m2) = isSubmapM (<=) m1 m2
fromListT s f xs = RMap (fromListM s (f . Rev) [(k, a) | (Rev k, a) <- xs])
fromAscListT s f xs = RMap (fromAscListM s (\ k -> flip (f (Rev k))) [(k, a) | (Rev k, a) <- L.reverse xs])
fromDistAscListT s xs = RMap (fromDistAscListM s [(k, a) | (Rev k, a) <- L.reverse xs])
reverse :: TrieMap k a -> TrieMap (Rev k) a
reverse = RMap
unreverse :: TrieMap (Rev k) a -> TrieMap k a
unreverse (RMap m) = m