witness-0.4: src/Data/Witness/WitnessFDict.hs
module Data.Witness.WitnessFDict where
{
import Data.Maybe;
import Data.Type.Equality;
import Data.Witness.Any;
-- | A dictionary that is heterogenous up to its simple witness type @w@.
-- Witnesses are the keys of the dictionary, and the values they witness are the values of the dictionary.
;
newtype WitnessFDict (w :: k -> *) (f :: k -> *) = MkWitnessFDict [AnyF w f];
-- | An empty dictionary.
;
emptyWitnessFDict :: WitnessFDict w f;
emptyWitnessFDict = MkWitnessFDict [];
-- | Look up the first value in the dictionary that matches the given witness.
;
witnessFDictLookup :: (TestEquality w) => w a -> WitnessFDict w f -> Maybe (f a);
witnessFDictLookup wit (MkWitnessFDict cells) = listToMaybe (mapMaybe (matchAnyF wit) cells);
-- | Modify the first value in the dictionary that matches a particular witness.
;
witnessFDictModify :: (TestEquality w) => w a -> (f a -> f a) -> WitnessFDict w f -> WitnessFDict w f;
witnessFDictModify wit amap (MkWitnessFDict cells) = MkWitnessFDict
(replaceFirst ((fmap ((MkAnyF wit) . amap)) . (matchAnyF wit)) cells) where
{
replaceFirst :: (a -> Maybe a) -> [a] -> [a];
replaceFirst ama (a:aa) = case ama a of
{
Just newa -> (newa:aa);
_ -> a : (replaceFirst ama aa);
};
replaceFirst _ _ = [];
};
-- | Replace the first value in the dictionary that matches the witness
;
witnessFDictReplace :: (TestEquality w) => w a -> f a -> WitnessFDict w f -> WitnessFDict w f;
witnessFDictReplace wit newfa = witnessFDictModify wit (const newfa);
-- | Add a witness and value as the first entry in the dictionary.
;
witnessFDictAdd :: w a -> f a -> WitnessFDict w f -> WitnessFDict w f;
witnessFDictAdd wit fa (MkWitnessFDict cells) = MkWitnessFDict ((MkAnyF wit fa):cells);
-- | Remove the first entry in the dictionary that matches the given witness.
;
witnessFDictRemove :: (TestEquality w) => w a -> WitnessFDict w f -> WitnessFDict w f;
witnessFDictRemove wit (MkWitnessFDict cells) = MkWitnessFDict
(removeFirst (\(MkAnyF cwit _) -> isJust (testEquality wit cwit)) cells) where
{
removeFirst :: (a -> Bool) -> [a] -> [a];
removeFirst p (a:as) | p a = as;
removeFirst p (a:as) = a : (removeFirst p as);
removeFirst _ _ = [];
};
-- | Create a dictionary from a list of witness\/value pairs
;
witnessFDictFromList :: [AnyF w f] -> WitnessFDict w f;
witnessFDictFromList = MkWitnessFDict;
}