-- ----------------------------------------------------------------------- -- The Dict type -- ----------------------------------------------------------------------- module Dict ( Dict, emptyDict, lookupDict, addToDict, delFromDict ) where import Data.Dynamic import Data.Maybe -- | Stores a set of elements with distinct types indexed by type -- NB. Needs to use a FiniteMap, when TypeRep's instance Ord. newtype Dict = Dict [(TypeRep,Dynamic)] -- | Dict with no elements. emptyDict :: Dict emptyDict = Dict [] -- | Retrieve an element from the dictionary, if one of that type exists. lookupDict :: Typeable a => Dict -> Maybe a lookupDict (Dict list) = let -- construct a dummy value of the required type so we can get at its -- TypeRep. Just dummy = (Just undefined) `asTypeOf` aOpt -- get at the required result type. dynOpt = lookup (typeOf dummy) list aOpt = case dynOpt of Nothing -> Nothing Just dyn -> Just ( fromMaybe (error "Inconsistent type in Dict") (fromDynamic dyn) ) in aOpt -- | Add an element to the dictionary if possible, or return Nothing if it -- isn't because one of that type already exists. addToDict :: Typeable a => Dict -> a -> Maybe Dict addToDict (Dict list) val = let typeRep = typeOf val in case lookup typeRep list of Just _ -> Nothing Nothing -> Just (Dict ((typeRep,toDyn val) : list)) -- | Delete an element from the dictionary, if one is in it, or return Nothing -- if it isn't. delFromDict :: Typeable a => Dict -> a -- ^ this value is only interesting for its type, and isn't looked at. -> Maybe Dict delFromDict (Dict list) val = let typeRep = typeOf val dList [] = Nothing dList ((hd@(typeRep2,_)):list2) = if typeRep == typeRep2 then Just list2 else fmap (hd:) (dList list2) in fmap Dict (dList list)