packages feed

tlex-core-0.1.0.0: src/Language/Lexer/Tlex/Data/EnumMap.hs

module Language.Lexer.Tlex.Data.EnumMap (
    EnumMap,
    empty,
    insert,
    assocs,
    keys,
    toAscList,
    toDescList,
    lookup,
    member,
    insertOrUpdate,
    fromList,
    foldlWithKey',
    update,
    delete,
    singleton,
    unionWith,
    intersectionWith,
    mapWithKey,
    mergeWithKey,
) where

import           Prelude            hiding (lookup)

import qualified Data.Coerce        as Coerce
import qualified Data.IntMap.Strict as IntMap


newtype EnumMap k a = EnumMap
    { unEnumMap :: IntMap.IntMap a
    }
    deriving (Eq, Show, Functor)

empty :: Enum k => EnumMap k a
empty = EnumMap IntMap.empty

singleton :: Enum k => k -> a -> EnumMap k a
singleton k x = EnumMap do IntMap.singleton (fromEnum k) x

insert :: Enum k => k -> a -> EnumMap k a -> EnumMap k a
insert k x (EnumMap m) = EnumMap do IntMap.insert (fromEnum k) x m

assocs :: Enum k => EnumMap k a -> [(k, a)]
assocs (EnumMap m) = [ (toEnum i, x) | (i, x) <- IntMap.assocs m ]

keys :: Enum k => EnumMap k a -> [k]
keys (EnumMap m) = [ toEnum k | k <- IntMap.keys m ]

toAscList :: Enum k => EnumMap k a -> [(k, a)]
toAscList (EnumMap m) = [ (toEnum i, x) | (i, x) <- IntMap.toAscList m ]

toDescList :: Enum k => EnumMap k a -> [(k, a)]
toDescList (EnumMap m) = [ (toEnum i, x) | (i, x) <- IntMap.toDescList m ]

lookup :: Enum k => k -> EnumMap k a -> Maybe a
lookup k (EnumMap m) = IntMap.lookup (fromEnum k) m

member :: Enum k => k -> EnumMap k a -> Bool
member k (EnumMap m) = IntMap.member (fromEnum k) m

insertOrUpdate :: Enum k => k -> a -> (a -> a) -> EnumMap k a -> EnumMap k a
insertOrUpdate k ~dx ~uf (EnumMap m) =
    let ik = fromEnum k
    in EnumMap case IntMap.lookup ik m of
        Nothing -> IntMap.insert ik dx m
        Just x  -> IntMap.insert ik (uf x) m

fromList :: Enum k => [(k, a)] -> EnumMap k a
fromList xs = EnumMap do IntMap.fromList [ (fromEnum i, x) | (i, x) <- xs ]

delete :: Enum k => k -> EnumMap k a -> EnumMap k a
delete k (EnumMap m) = EnumMap do IntMap.delete (fromEnum k) m

foldlWithKey' :: Enum k => (b -> k -> a -> b) -> b -> EnumMap k a -> b
foldlWithKey' f acc0 (EnumMap m) = IntMap.foldlWithKey' (\acc i x -> f acc (toEnum i) x) acc0 m

update :: Enum k => (a -> Maybe a) -> k -> EnumMap k a -> EnumMap k a
update f k (EnumMap m) = EnumMap do IntMap.update f (fromEnum k) m

unionWith :: Enum k => (a -> a -> a) -> EnumMap k a -> EnumMap k a -> EnumMap k a
unionWith f (EnumMap m1) (EnumMap m2) = EnumMap do IntMap.unionWith f m1 m2

intersectionWith :: Enum k => (a -> a -> a) -> EnumMap k a -> EnumMap k a -> EnumMap k a
intersectionWith f (EnumMap m1) (EnumMap m2) = EnumMap do IntMap.intersectionWith f m1 m2

mapWithKey :: Enum k => (k -> a -> b) -> EnumMap k a -> EnumMap k b
mapWithKey f (EnumMap m) = EnumMap do
    IntMap.mapWithKey
        do \i x -> f (toEnum i) x
        do m

mergeWithKey :: Enum k
    => (k -> a -> b -> Maybe c)
    -> (EnumMap k a -> EnumMap k c)
    -> (EnumMap k b -> EnumMap k c)
    -> EnumMap k a -> EnumMap k b -> EnumMap k c
mergeWithKey f g1 g2 (EnumMap m1) (EnumMap m2) = EnumMap do
    IntMap.mergeWithKey
        do \i x y -> f (toEnum i) x y
        do \m -> Coerce.coerce g1 m
        do \m -> Coerce.coerce g2 m
        do m1
        do m2