{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} ------------------------------------------------------------------------------------------- -- Abstraction of Map like datatypes providing lookup ------------------------------------------------------------------------------------------- module CHR.Data.Lookup.Types ( Lookup(..) , LookupApply(..) , alterDefault ) where ------------------------------------------------------------------------------------------- import qualified Data.Set as Set import Control.Arrow import Prelude hiding (lookup, map) import qualified Data.List as List ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- Lookup ------------------------------------------------------------------------------------------- -- | Class interface uses same names as Data.Map. -- Instances must define: 'lookup', 'findMin', 'findMax', 'fromList', 'toList', 'null', 'alter'. -- Union is left-biased in that left operand values overwrite right operand values, but all other context/info (if any and/or relevant, like scope) is inherited from the right one. class Lookup c k v | c -> k, c -> v where -- core functionality -- extraction lookup :: k -> c -> Maybe v {- findMin :: c -> (k, v) findMax :: c -> (k, v) -} -- (de)construction fromList :: [(k,v)] -> c toList :: c -> [(k,v)] -- properties null :: c -> Bool size :: c -> Int -- update catchall alter :: (Maybe v -> Maybe v) -> k -> c -> c -- derived functionality, included as to allow optimization singleton :: k -> v -> c empty :: c insertWith :: (v -> v -> v) -> k -> v -> c -> c insert :: k -> v -> c -> c unionWith :: (v -> v -> v) -> c -> c -> c union :: c -> c -> c unionsWith :: (v -> v -> v) -> [c] -> c unions :: [c] -> c delete :: k -> c -> c keys :: c -> [k] keysSet :: Ord k => c -> Set.Set k elems :: c -> [v] map :: (v -> v) -> c -> c -- defs for functions of which def is optional singleton k v = fromList [(k,v)] empty = fromList [] insertWith f k v c = alter (Just . maybe v (f v)) k c insert = insertWith const unionWith f c1 c2 = foldr (uncurry $ insertWith f) c2 $ toList c1 union = unionWith const unionsWith f [] = empty unionsWith f l = foldr1 (unionWith f) l unions = unionsWith const delete = alter (const Nothing) keys = List.map fst . toList keysSet = Set.fromList . keys elems = List.map snd . toList map f = fromList . List.map (second f) . toList null c = size c == 0 -- | Default for 'alter' when 'lookup', 'insert' (or 'inserWith'), and 'delete' are defined alterDefault :: Lookup c k v => (Maybe v -> Maybe v) -> k -> c -> c alterDefault f k c = case f $ lookup k c of Just v -> insert k v c _ -> delete k c ------------------------------------------------------------------------------------------- -- Lookup application, fixing the combination ------------------------------------------------------------------------------------------- class LookupApply l1 l2 where apply :: l1 -> l2 -> l2