module GHC.Data.TrieMap(
MaybeMap,
ListMap,
LiteralMap,
TrieMap(..), insertTM, deleteTM, foldMapTM, isEmptyTM,
(>.>), (|>), (|>>), XT,
foldMaybe, filterMaybe,
GenMap,
lkG, xtG, mapG, fdG,
xtList, lkList
) where
import GHC.Prelude
import GHC.Types.Literal
import GHC.Types.Unique.DFM
import GHC.Types.Unique( Uniquable )
import qualified Data.Map as Map
import qualified Data.IntMap as IntMap
import GHC.Utils.Outputable
import Control.Monad( (>=>) )
import Data.Kind( Type )
import qualified Data.Semigroup as S
type XT a = Maybe a -> Maybe a
class TrieMap m where
type Key m :: Type
emptyTM :: m a
lookupTM :: forall b. Key m -> m b -> Maybe b
alterTM :: forall b. Key m -> XT b -> m b -> m b
mapTM :: (a->b) -> m a -> m b
filterTM :: (a -> Bool) -> m a -> m a
foldTM :: (a -> b -> b) -> m a -> b -> b
insertTM :: TrieMap m => Key m -> a -> m a -> m a
insertTM k v m = alterTM k (\_ -> Just v) m
deleteTM :: TrieMap m => Key m -> m a -> m a
deleteTM k m = alterTM k (\_ -> Nothing) m
foldMapTM :: (TrieMap m, Monoid r) => (a -> r) -> m a -> r
foldMapTM f m = foldTM (\ x r -> f x S.<> r) m mempty
isEmptyTM :: TrieMap m => m a -> Bool
isEmptyTM m = foldTM (\ _ _ -> False) m True
(>.>) :: (a -> b) -> (b -> c) -> a -> c
infixr 1 >.>
(f >.> g) x = g (f x)
infixr 1 |>, |>>
(|>) :: a -> (a->b) -> b
x |> f = f x
(|>>) :: TrieMap m2
=> (XT (m2 a) -> m1 (m2 a) -> m1 (m2 a))
-> (m2 a -> m2 a)
-> m1 (m2 a) -> m1 (m2 a)
(|>>) f g = f (Just . g . deMaybe)
deMaybe :: TrieMap m => Maybe (m a) -> m a
deMaybe Nothing = emptyTM
deMaybe (Just m) = m
instance TrieMap IntMap.IntMap where
type Key IntMap.IntMap = Int
emptyTM = IntMap.empty
lookupTM k m = IntMap.lookup k m
alterTM = xtInt
foldTM k m z = IntMap.foldr k z m
mapTM f m = IntMap.map f m
filterTM f m = IntMap.filter f m
xtInt :: Int -> XT a -> IntMap.IntMap a -> IntMap.IntMap a
xtInt k f m = IntMap.alter f k m
instance Ord k => TrieMap (Map.Map k) where
type Key (Map.Map k) = k
emptyTM = Map.empty
lookupTM = Map.lookup
alterTM k f m = Map.alter f k m
foldTM k m z = Map.foldr k z m
mapTM f m = Map.map f m
filterTM f m = Map.filter f m
instance forall key. Uniquable key => TrieMap (UniqDFM key) where
type Key (UniqDFM key) = key
emptyTM = emptyUDFM
lookupTM k m = lookupUDFM m k
alterTM k f m = alterUDFM f m k
foldTM k m z = foldUDFM k z m
mapTM f m = mapUDFM f m
filterTM f m = filterUDFM f m
data MaybeMap m a = MM { mm_nothing :: Maybe a, mm_just :: m a }
instance TrieMap m => TrieMap (MaybeMap m) where
type Key (MaybeMap m) = Maybe (Key m)
emptyTM = MM { mm_nothing = Nothing, mm_just = emptyTM }
lookupTM = lkMaybe lookupTM
alterTM = xtMaybe alterTM
foldTM = fdMaybe
mapTM = mapMb
filterTM = ftMaybe
instance TrieMap m => Foldable (MaybeMap m) where
foldMap = foldMapTM
mapMb :: TrieMap m => (a->b) -> MaybeMap m a -> MaybeMap m b
mapMb f (MM { mm_nothing = mn, mm_just = mj })
= MM { mm_nothing = fmap f mn, mm_just = mapTM f mj }
lkMaybe :: (forall b. k -> m b -> Maybe b)
-> Maybe k -> MaybeMap m a -> Maybe a
lkMaybe _ Nothing = mm_nothing
lkMaybe lk (Just x) = mm_just >.> lk x
xtMaybe :: (forall b. k -> XT b -> m b -> m b)
-> Maybe k -> XT a -> MaybeMap m a -> MaybeMap m a
xtMaybe _ Nothing f m = m { mm_nothing = f (mm_nothing m) }
xtMaybe tr (Just x) f m = m { mm_just = mm_just m |> tr x f }
fdMaybe :: TrieMap m => (a -> b -> b) -> MaybeMap m a -> b -> b
fdMaybe k m = foldMaybe k (mm_nothing m)
. foldTM k (mm_just m)
ftMaybe :: TrieMap m => (a -> Bool) -> MaybeMap m a -> MaybeMap m a
ftMaybe f (MM { mm_nothing = mn, mm_just = mj })
= MM { mm_nothing = filterMaybe f mn, mm_just = filterTM f mj }
foldMaybe :: (a -> b -> b) -> Maybe a -> b -> b
foldMaybe _ Nothing b = b
foldMaybe k (Just a) b = k a b
filterMaybe :: (a -> Bool) -> Maybe a -> Maybe a
filterMaybe _ Nothing = Nothing
filterMaybe f input@(Just x) | f x = input
| otherwise = Nothing
data ListMap m a
= LM { lm_nil :: Maybe a
, lm_cons :: m (ListMap m a) }
instance TrieMap m => TrieMap (ListMap m) where
type Key (ListMap m) = [Key m]
emptyTM = LM { lm_nil = Nothing, lm_cons = emptyTM }
lookupTM = lkList lookupTM
alterTM = xtList alterTM
foldTM = fdList
mapTM = mapList
filterTM = ftList
instance TrieMap m => Foldable (ListMap m) where
foldMap = foldMapTM
instance (TrieMap m, Outputable a) => Outputable (ListMap m a) where
ppr m = text "List elts" <+> ppr (foldTM (:) m [])
mapList :: TrieMap m => (a->b) -> ListMap m a -> ListMap m b
mapList f (LM { lm_nil = mnil, lm_cons = mcons })
= LM { lm_nil = fmap f mnil, lm_cons = mapTM (mapTM f) mcons }
lkList :: TrieMap m => (forall b. k -> m b -> Maybe b)
-> [k] -> ListMap m a -> Maybe a
lkList _ [] = lm_nil
lkList lk (x:xs) = lm_cons >.> lk x >=> lkList lk xs
xtList :: TrieMap m => (forall b. k -> XT b -> m b -> m b)
-> [k] -> XT a -> ListMap m a -> ListMap m a
xtList _ [] f m = m { lm_nil = f (lm_nil m) }
xtList tr (x:xs) f m = m { lm_cons = lm_cons m |> tr x |>> xtList tr xs f }
fdList :: forall m a b. TrieMap m
=> (a -> b -> b) -> ListMap m a -> b -> b
fdList k m = foldMaybe k (lm_nil m)
. foldTM (fdList k) (lm_cons m)
ftList :: TrieMap m => (a -> Bool) -> ListMap m a -> ListMap m a
ftList f (LM { lm_nil = mnil, lm_cons = mcons })
= LM { lm_nil = filterMaybe f mnil, lm_cons = mapTM (filterTM f) mcons }
type LiteralMap a = Map.Map Literal a
data GenMap m a
= EmptyMap
| SingletonMap (Key m) a
| MultiMap (m a)
instance (Outputable a, Outputable (m a)) => Outputable (GenMap m a) where
ppr EmptyMap = text "Empty map"
ppr (SingletonMap _ v) = text "Singleton map" <+> ppr v
ppr (MultiMap m) = ppr m
instance (Eq (Key m), TrieMap m) => TrieMap (GenMap m) where
type Key (GenMap m) = Key m
emptyTM = EmptyMap
lookupTM = lkG
alterTM = xtG
foldTM = fdG
mapTM = mapG
filterTM = ftG
instance (Eq (Key m), TrieMap m) => Foldable (GenMap m) where
foldMap = foldMapTM
lkG :: (Eq (Key m), TrieMap m) => Key m -> GenMap m a -> Maybe a
lkG _ EmptyMap = Nothing
lkG k (SingletonMap k' v') | k == k' = Just v'
| otherwise = Nothing
lkG k (MultiMap m) = lookupTM k m
xtG :: (Eq (Key m), TrieMap m) => Key m -> XT a -> GenMap m a -> GenMap m a
xtG k f EmptyMap
= case f Nothing of
Just v -> SingletonMap k v
Nothing -> EmptyMap
xtG k f m@(SingletonMap k' v')
| k' == k
= case f (Just v') of
Just v'' -> SingletonMap k' v''
Nothing -> EmptyMap
| otherwise
= case f Nothing of
Nothing -> m
Just v -> emptyTM |> alterTM k' (const (Just v'))
>.> alterTM k (const (Just v))
>.> MultiMap
xtG k f (MultiMap m) = MultiMap (alterTM k f m)
mapG :: TrieMap m => (a -> b) -> GenMap m a -> GenMap m b
mapG _ EmptyMap = EmptyMap
mapG f (SingletonMap k v) = SingletonMap k (f v)
mapG f (MultiMap m) = MultiMap (mapTM f m)
fdG :: TrieMap m => (a -> b -> b) -> GenMap m a -> b -> b
fdG _ EmptyMap = \z -> z
fdG k (SingletonMap _ v) = \z -> k v z
fdG k (MultiMap m) = foldTM k m
ftG :: TrieMap m => (a -> Bool) -> GenMap m a -> GenMap m a
ftG _ EmptyMap = EmptyMap
ftG f input@(SingletonMap _ v)
| f v = input
| otherwise = EmptyMap
ftG f (MultiMap m) = MultiMap (filterTM f m)