module Data.Ref.Map (
Map
, Name
, empty
, singleton
, null
, size
, member
, (!)
, lookup
, insert
, delete
, adjust
, filter
, hmap
, union
, difference
, intersection
, Entry(..)
, elems
) where
import Control.Applicative ((<$>))
import Data.Ref
import Data.List (find, deleteBy)
import Data.Function (on)
import Unsafe.Coerce
import System.Mem.StableName
import Data.IntMap (IntMap)
import qualified Data.IntMap as M
import Prelude hiding (null, lookup, map, filter)
type Name = StableName
data HideType f where
Hide :: f a -> HideType f
data Map f = Map (IntMap [(HideType Name, HideType f)])
empty :: Map f
empty = Map M.empty
singleton :: Name a -> f a -> Map f
singleton n v = Map $ M.singleton (hashStableName n) [(Hide n, Hide v)]
null :: Map f -> Bool
null (Map m) = M.null m
size :: Map f -> Int
size (Map m) = M.size m
member :: Name a -> Map f -> Bool
member n (Map m) = M.member (hashStableName n) m
(!) :: Map f -> Name a -> f a
(!) m name = maybe (error "Data.Ref.Map.(!)") id (lookup name m)
lookup :: Name a -> Map f -> Maybe (f a)
lookup n (Map m) = case M.lookup (hashStableName n) m of
Nothing -> Nothing
Just xs -> case find (\(Hide x,_) -> eqStableName x n) xs of
Nothing -> Nothing
Just (_,Hide f) -> Just $ unsafeCoerce f
insert :: Ref a -> f a -> Map f -> Map f
insert (Ref n _) v (Map m) = Map $ M.insertWith (++) (hashStableName n) [(Hide n, Hide v)] m
delete :: forall f a. Name a -> Map f -> Map f
delete n map@(Map m) = Map $ M.update del (hashStableName n) m
where
del :: [(HideType Name, HideType f)] -> Maybe [(HideType Name, HideType f)]
del [] = Nothing
del xs = Just $ deleteBy eq (Hide n, undefined) xs
eq :: (HideType Name, x) -> (HideType Name, y) -> Bool
eq (Hide x, _) (Hide y, _) = x `eqStableName` y
adjust :: forall f a b. (f a -> f b) -> Name a -> Map f -> Map f
adjust f n (Map m) = Map $ M.adjust (fmap open) (hashStableName n) m
where
open :: (HideType Name, HideType f) -> (HideType Name, HideType f)
open pair@(Hide x, Hide v)
| x `eqStableName` n = (Hide x, Hide $ f $ unsafeCoerce v)
| otherwise = pair
filter :: (forall a. f a -> Bool) -> Map f -> Map f
filter f (Map m) = Map $ M.filter (unwrap f) m
where
unwrap :: (forall a. f a -> Bool) -> [(HideType Name, HideType f)] -> Bool
unwrap f = and . fmap (\(_, Hide a) -> f a)
hmap :: forall f h a. (f a -> h a) -> Map f -> Map h
hmap f (Map m) = Map $ M.map (fmap $ fmap open) m
where
open :: HideType f -> HideType h
open (Hide x) = Hide $ f $ unsafeCoerce x
union :: Map f -> Map f -> Map f
union (Map m) (Map n) = Map $ M.union m n
difference :: Map f -> Map f -> Map f
difference (Map m) (Map n) = Map $ M.difference m n
intersection :: Map f -> Map f -> Map f
intersection (Map m) (Map n) = Map $ M.intersection m n
data Entry f = forall a. Entry (Name a) (f a)
elems :: Map f -> [Entry f]
elems (Map m) = fmap pack . concat $ M.elems m
where
pack :: (HideType Name, HideType f) -> Entry f
pack (Hide n, Hide f) = Entry n (unsafeCoerce f)