{-# LANGUAGE ExistentialQuantification
, ScopedTypeVariables
, TypeOperators
, ConstraintKinds
, MultiParamTypeClasses
, FlexibleInstances
, ViewPatterns
, PolyKinds
#-}
module Data.HtsCSet ( HtsCSet
, empty, emptyP, singleton, singletonP
, null, size, member, notMember
, existTypeOf, existTypeOfP, existTypeOfP'
, appl, compliance
, insert
, lookup, lookupWithDefault
, update
, deleteByType, deleteByTypeP, deleteByTypeP', deleteWhen
, (:+) (..), Append (..), fill
, Proxy(..)
) where
import qualified Data.Map as M
import Data.Typeable
import GHC.Exts (Constraint)
import Prelude hiding (lookup, null)
data CastBox c = forall a. (Typeable a, c a) => CastBox { unBox :: a }
newtype HtsCSet c = HtsCSet { unHS :: M.Map TypeRep (CastBox c) }
mapCastBox :: forall c a. (Typeable a, c a) => (a -> a) -> CastBox c -> CastBox c
mapCastBox f o@(CastBox e) = case cast e of
(Just e') -> CastBox (f e')
Nothing -> o
empty :: HtsCSet c
empty = HtsCSet M.empty
emptyP :: proxy c -> HtsCSet c
emptyP _ = empty
singleton :: forall c a. (Typeable a, c a) => a -> HtsCSet c
singleton a = HtsCSet (M.singleton (typeRep (Proxy :: Proxy a)) (CastBox a))
singletonP :: forall proxy c a. (Typeable a, c a) => proxy c -> a -> HtsCSet c
singletonP _ = singleton
null :: HtsCSet c -> Bool
null = M.null . unHS
size :: HtsCSet c -> Int
size = M.size . unHS
member :: forall proxy c a. (Typeable a, Eq a, c a) => a -> HtsCSet c -> Bool
member elem (HtsCSet hs) = case M.lookup (typeRep (Proxy :: Proxy a)) hs of
(Just (CastBox (cast -> Just elem'))) -> elem == elem'
_ -> False
notMember :: forall proxy c a. (Typeable a, Eq a, c a) => a -> HtsCSet c -> Bool
notMember elem (HtsCSet hs) = case M.lookup (typeRep (Proxy :: Proxy a)) hs of
(Just (CastBox (cast -> Just elem'))) -> elem /= elem'
_ -> True
existTypeOf :: forall c a. (Typeable a, c a) => a -> HtsCSet c -> Bool
existTypeOf _ (HtsCSet hs) = case M.lookup (typeRep (Proxy :: Proxy a)) hs of
(Just _) -> True
_ -> False
existTypeOfP :: forall proxy c a. (Typeable a, c a) => proxy a -> HtsCSet c -> Bool
existTypeOfP _ (HtsCSet hs) = case M.lookup (typeRep (Proxy :: Proxy a)) hs of
(Just _) -> True
_ -> False
existTypeOfP' :: forall c a. (Typeable a, c a) => Proxy a -> HtsCSet c -> Bool
existTypeOfP' _ (HtsCSet hs) = case M.lookup (typeRep (Proxy :: Proxy a)) hs of
(Just _) -> True
_ -> False
appl :: forall a b c. (Typeable a, c a) => b -> (a -> b) -> HtsCSet c -> b
appl def fn hs = case lookup hs of
Nothing -> def
(Just a) -> fn a
compliance :: forall a c. (Typeable a, c a) => Bool -> (a -> Bool) -> HtsCSet c -> Bool
compliance = appl
insert :: forall c a. (Typeable a, c a) => a -> HtsCSet c -> HtsCSet c
insert a (HtsCSet hs) = HtsCSet (M.insert (typeRep (Proxy :: Proxy a)) (CastBox a) hs)
lookup :: forall c a. (Typeable a, c a) => HtsCSet c -> Maybe a
lookup (HtsCSet hs) = case M.lookup (typeRep (Proxy :: Proxy a)) hs of
(Just (CastBox a)) -> cast a
_ -> Nothing
lookupWithDefault :: forall c a. (Typeable a, c a) => a -> HtsCSet c -> a
lookupWithDefault a hs = case lookup hs of
Nothing -> a
(Just a') -> a'
update :: forall c a. (Typeable a, c a) => (a -> a) -> HtsCSet c -> HtsCSet c
update f = HtsCSet . M.adjust (mapCastBox f) (typeRep (Proxy :: Proxy a)) . unHS
deleteByType :: forall a c. (Typeable a, c a) => a -> HtsCSet c -> HtsCSet c
deleteByType _ = HtsCSet . M.delete (typeRep (Proxy :: Proxy a)) . unHS
deleteByTypeP :: forall proxy c a. (Typeable a, c a) => proxy a -> HtsCSet c -> HtsCSet c
deleteByTypeP _ = HtsCSet . M.delete (typeRep (Proxy :: Proxy a)) . unHS
deleteByTypeP' :: forall a c. (Typeable a, c a) => Proxy a -> HtsCSet c -> HtsCSet c
deleteByTypeP' _ = HtsCSet . M.delete (typeRep (Proxy :: Proxy a)) . unHS
deleteWhen :: forall a c. (Typeable a, c a) => (a -> Bool) -> HtsCSet c -> HtsCSet c
deleteWhen cond hs = case lookup hs of
Nothing -> hs
(Just a) -> if cond a then deleteByType a hs else hs
data a :+ b = a :+ b
infixr 5 :+
class Append c a where
append :: a -> HtsCSet c -> HtsCSet c
fill :: (Append c a) => a -> HtsCSet c
fill = flip append empty
instance (Typeable a, c a, Append c b) => Append c (a :+ b) where
append (a :+ b) = insert a . (append b)
instance Append c () where
append _ hs = hs