multimap 1.1 → 1.2
raw patch · 4 files changed
+451/−275 lines, 4 files
Files
- multimap.cabal +10/−3
- src/Data/MultiMap.hs +281/−0
- src/Data/Multimap.hs +0/−272
- src/Data/SetMap.hs +160/−0
multimap.cabal view
@@ -1,10 +1,16 @@ Name: multimap-Version: 1.1+Version: 1.2 Synopsis: A multimap. Description: This is a simple implementation of a multimap, based on "Data.Map". .- [@v1.1@] @!@ had its arguments flipped. Fixed.+ [@v1.1@]+ @!@ had its arguments flipped. Fixed. Also added @fromMap@.+ .+ [@v1.2]+ Added "Data.SetMap", renamed @Multimap@ to "Data.MultiMap".+ Fixed the type of @delete@. Derive instances for @Data@+ and @Typeable@. License: MIT License-File: LICENSE@@ -21,7 +27,8 @@ location: hub.darcs.net:multimap Library- Exposed-Modules: Data.Multimap+ Exposed-Modules: Data.MultiMap+ , Data.SetMap Build-Depends: base >= 3 && < 5, containers Hs-Source-Dirs: src
+ src/Data/MultiMap.hs view
@@ -0,0 +1,281 @@+{-# LANGUAGE Haskell2010+ , DeriveDataTypeable+ #-}+{-# OPTIONS+ -Wall+ -fno-warn-name-shadowing+ #-}++-- | A very simple MultiMap, based on 'Data.Map.Map' from the containers package.+module Data.MultiMap (++ -- * MultiMap type+ MultiMap,++ -- * Query+ null,+ size,+ numKeys,+ numValues,++ member,+ notMember,+ lookup,++ -- * Operators+ (!),++ -- * Construction+ empty,+ + -- ** Insertion+ insert,++ -- ** Delete+ delete,++ -- * Traversal+ map,+ mapKeys,+ mapWithKey,+ + -- * Folds+ foldr,+ foldl,+ foldrWithKey,+ foldlWithKey,++ -- * Conversion+ elems,+ keys,+ keysSet,+ assocs,++ toMap,+ toMapOfSets,+ toList,+ fromList,+ fromMap,+ + -- * Min/Max+ findMin,+ findMax,+ findMinWithValues,+ findMaxWithValues++ ) where++import Prelude hiding (lookup, map, null, foldr, foldl)+import qualified Prelude as P++import qualified Data.Set as Set+import Data.Set (Set)++import qualified Data.Map as Map+import Data.Map (Map)++import Data.Word+import Data.Data+++-- | A MultiMap with keys @k@ and values @v@.+--+-- A key can have multiple values (but not zero).+-- The same value can be added multiple times (thus no+-- constraints are ever imposed on @v@).+--+-- Internally this is simply a @Map k [v]@.+-- See 'toMap' for accessing the underlying 'Map'.+newtype MultiMap k v = MultiMap (Word32, Word32, Map k [v])+ deriving (Data, Typeable)+++null :: MultiMap k a -> Bool+-- ^ /O(1)./ Check whether the multimap is empty or not.+null (MultiMap (_, _, m)) = Map.null m+++size :: MultiMap k a -> Int+-- ^ /O(1)./ The number of elements in the multimap.+size (MultiMap (_, size, _)) = fromIntegral size+++numKeys :: MultiMap k a -> Word32+-- ^ /O(1)./ The number of keys in the multimap.+-- +-- As this is a multimap, the number of keys is not+-- necessarily equal to the number of values.+numKeys (MultiMap (nk, _, _)) = nk+++numValues :: MultiMap k a -> Word32+-- ^ /O(1)./ The number of values in the multimap.+--+-- As this is a multimap, the number of keys is not+-- necessarily equal to the number of values.+numValues (MultiMap (_, nv, _)) = nv+++notMember, member :: Ord k => MultiMap k a -> k -> Bool+-- | /O(log n)./ Is the key a member of the multimap?+member (MultiMap (_, _, map)) key = Map.member key map+-- | /O(log n)./ Is the key not a member of the multimap?+notMember key = not . member key+++(!) :: Ord k => MultiMap k a -> k -> [a]+-- ^ As @flip lookup@+(!) = flip lookup+++lookup :: Ord k => k -> MultiMap k a -> [a]+-- ^ /O(log n)./ Lookup the value at a key in the map.+--+-- The function will return the corrsponding values as a List, or the+-- empty list if no values are associated witht the given key.+lookup key (MultiMap (_, _, map)) = maybe [] id (Map.lookup key map)+++empty :: MultiMap k a+-- ^ /O(1)./ The empty multimap.+empty = MultiMap (0, 0, Map.empty)+++insert :: Ord k => k -> a -> MultiMap k a -> MultiMap k a+-- ^ /O(log n)./ Insert a new key and value in the map.+insert k v (MultiMap (nk, nv, map))+ | Map.member k map = MultiMap (nk, succ nv, Map.insert k (v : map Map.! k) map)+ | otherwise = MultiMap (succ nk, succ nv, Map.insert k [v] map)++delete :: Ord k => k -> MultiMap k a -> MultiMap k a+-- ^ /O(log n)./ Delete a key and all its values from the map.+delete k m@(MultiMap (nk, nv, map)) = case Map.lookup k map of+ Just v -> MultiMap (pred nk, nv - fromIntegral (length v), Map.delete k map)+ _ -> m+++map :: (a -> b) -> MultiMap k a -> MultiMap k b+-- ^ Map a function over all values in the map.+map f (MultiMap (nk, nv, map)) = MultiMap (nk, nv, Map.map (P.map f) map)+++mapKeys :: Ord k2 => (k1 -> k2) -> MultiMap k1 a -> MultiMap k2 a+-- ^ mapKeys f s is the multimap obtained by applying f to each key of s.+mapKeys f (MultiMap (nk, nv, map)) = MultiMap (nk, nv, Map.mapKeys f map)+++mapWithKey :: (k -> a -> b) -> MultiMap k a -> MultiMap k b+-- ^ Map a function over all key/value pairs in the map.+mapWithKey f (MultiMap (nk, nv, map))+ = MultiMap (nk, nv, Map.mapWithKey (\k -> P.map (f k)) map)+++foldr :: (a -> b -> b) -> b -> MultiMap k a -> b+-- ^ Fold the values in the map using the given right-associative binary operator.+foldr f e = P.foldr f e . concat . elems+++foldl :: (a -> b -> a) -> a -> MultiMap k b -> a+-- ^ Fold the values in the map using the given left-associative binary operator.+foldl f e = P.foldl f e . concat . elems+++foldrWithKey :: (k -> a -> b -> b) -> b -> MultiMap k a -> b+-- ^ /O(n)./ Fold the keys and values in the map using the given right-associative+-- binary operator, taking into account not only the value but also the key.+foldrWithKey f e = P.foldr (uncurry f) e . toList+++foldlWithKey :: (a -> k -> b -> a) -> a -> MultiMap k b -> a+-- ^ /O(n)./ Fold the keys and values in the map using the given left-associative+-- binary operator, taking into account not only the value but also the key.+foldlWithKey f e = P.foldl (\a (k,v) -> f a k v) e . toList+++elems :: MultiMap k a -> [[a]]+-- ^ /O(n)./ Return all elements of the multimap in the+-- ascending order of their keys.+--+-- A list of lists is returned since a key can have+-- multiple values. Use 'concat' to flatten.+elems (MultiMap (_, _, map)) = Map.elems map+++keys :: MultiMap k a -> [k]+-- ^ /O(n)./ Return all keys of the multimap in ascending order.+keys (MultiMap (_, _, map)) = Map.keys map+++keysSet :: MultiMap k a -> Set k+-- ^ /O(n)./ The set of all keys of the multimap.+keysSet (MultiMap (_, _, map)) = Map.keysSet map+++assocs :: MultiMap k a -> [(k, [a])]+-- ^ /O(n)./ Return all key/value pairs in the multimap+-- in ascending key order.+assocs (MultiMap (_, _, map)) = Map.assocs map+++toMap :: MultiMap k a -> Map k [a]+-- ^ /O(1)./ Return the map of lists.+toMap (MultiMap (_, _, theUnderlyingMap)) = theUnderlyingMap+++toMapOfSets :: Ord a => MultiMap k a -> Map k (Set a)+-- ^ /O(k*m*log m) where k is the number of keys and m the+-- maximum number of elements associated with a single key/+toMapOfSets (MultiMap (_, _, map)) = Map.map Set.fromList map+++toList :: MultiMap k a -> [(k, a)]+-- ^ Return a flattened list of key/value pairs.+toList (MultiMap (_, _, map))+ = concat $ Map.elems $ Map.mapWithKey (\k -> zip (repeat k)) map+++fromList :: Ord k => [(k, a)] -> MultiMap k a+-- ^ /O(n*log n)/ Create a multimap from a list of key/value pairs.+--+-- > fromList xs == foldr (uncurry insert) empty+fromList = P.foldr (uncurry insert) empty+++fromMap :: Map k [a] -> MultiMap k a+-- ^ Turns a map of lists into a multimap.+fromMap map = MultiMap (numKeys, numValues, map)+ where+ numKeys = fromIntegral $ Map.size map+ numValues = fromIntegral $ Map.foldr (\v s -> length v + s) 0 map+++findMin :: MultiMap k a -> Maybe k+-- ^ /O(log n)/ Find the minimal key of the multimap.+findMin (MultiMap (_, _, map))+ | Map.null map = Nothing+ | otherwise = Just $ fst $ Map.findMin map+++findMax :: MultiMap k a -> Maybe k+-- ^ /O(log n)/ Find the maximal key of the multimap.+findMax (MultiMap (_, _, map))+ | Map.null map = Nothing+ | otherwise = Just $ fst $ Map.findMax map+++findMinWithValues :: MultiMap k a -> Maybe (k, [a])+-- ^ /O(log n)/ Find the minimal key and the values associated with it.+findMinWithValues (MultiMap (_, _, map))+ | Map.null map = Nothing+ | otherwise = Just $ Map.findMin map+++findMaxWithValues :: MultiMap k a -> Maybe (k, [a])+-- ^ /O(log n)/ Find the maximal key and the values associated with it.+findMaxWithValues (MultiMap (_, _, map))+ | Map.null map = Nothing+ | otherwise = Just $ Map.findMax map++++
− src/Data/Multimap.hs
@@ -1,272 +0,0 @@-{-# LANGUAGE Haskell2010 #-}---- | A very simple Multimap, based on 'Data.Map.Map' from the containers package.-module Data.Multimap (-- -- * Multimap type- Multimap,-- -- * Query- null,- size,- numKeys,- numValues,-- member,- notMember,- lookup,-- -- * Operators- (!),-- -- * Construction- empty,- - -- ** Insertion- insert,-- -- ** Delete- delete,-- -- * Traversal- map,- mapKeys,- mapWithKey,- - -- * Folds- foldr,- foldl,- foldrWithKey,- foldlWithKey,-- -- * Conversion- elems,- keys,- keysSet,- assocs,-- toMap,- toMapOfSets,- toList,- fromList,- fromMap,- - -- * Min/Max- findMin,- findMax,- findMinWithValues,- findMaxWithValues-- ) where--import Prelude hiding (lookup, map, null, foldr, foldl)-import qualified Prelude as P--import qualified Data.Set as Set-import Data.Set (Set)--import qualified Data.Map as Map-import Data.Map (Map)--import Data.Word---- | A Multimap with keys @k@ and values @v@.------ A key can have multiple values (but not zero).--- The same value can be added multiple times (thus no--- constraints are ever imposed on @v@).------ Internally this is simply a @Map k [v]@.--- See 'toMap' for accessing the underlying 'Map'.-newtype Multimap k v = Multimap (Word32, Word32, Map k [v])---null :: Multimap k a -> Bool--- ^ /O(1)./ Check whether the multimap is empty or not.-null (Multimap (_, _, m)) = Map.null m---size :: Multimap k a -> Int--- ^ /O(1)./ The number of elements in the multimap.-size (Multimap (_, size, _)) = fromIntegral size---numKeys :: Multimap k a -> Word32--- ^ /O(1)./ The number of keys in the multimap.--- --- As this is a multimap, the number of keys is not--- necessarily equal to the number of values.-numKeys (Multimap (nk, _, _)) = nk---numValues :: Multimap k a -> Word32--- ^ /O(1)./ The number of values in the multimap.------ As this is a multimap, the number of keys is not--- necessarily equal to the number of values.-numValues (Multimap (_, nv, _)) = nv---notMember, member :: Ord k => Multimap k a -> k -> Bool--- | /O(log n)./ Is the key a member of the multimap?-member (Multimap (_, _, map)) key = Map.member key map--- | /O(log n)./ Is the key not a member of the multimap?-notMember key = not . member key---(!) :: Ord k => Multimap k a -> k -> [a]--- ^ As @flip lookup@-(!) = flip lookup---lookup :: Ord k => k -> Multimap k a -> [a]--- ^ /O(log n)./ Lookup the value at a key in the map.------ The function will return the corrsponding values as a List, or the--- empty list if no values are associated witht the given key.-lookup key (Multimap (_, _, map)) = maybe [] id (Map.lookup key map)---empty :: Multimap k a--- ^ /O(1)./ The empty multimap.-empty = Multimap (0, 0, Map.empty)---insert :: Ord k => k -> a -> Multimap k a -> Multimap k a--- ^ /O(log n)./ Insert a new key and value in the map.-insert k v (Multimap (nk, nv, map))- | Map.member k map = Multimap (nk, succ nv, Map.insert k (v : map Map.! k) map)- | otherwise = Multimap (succ nk, succ nv, Map.insert k [v] map)--delete :: Ord k => k -> a -> Multimap k a -> Multimap k a--- ^ /O(log n)./ Delete a key and all its values from the map.-delete k v m@(Multimap (nk, nv, map)) = case Map.lookup k map of- Just v -> Multimap (pred nk, nv - fromIntegral (length v), Map.delete k map)- _ -> m---map :: (a -> b) -> Multimap k a -> Multimap k b--- ^ Map a function over all values in the map.-map f (Multimap (nk, nv, map)) = Multimap (nk, nv, Map.map (P.map f) map)---mapKeys :: Ord k2 => (k1 -> k2) -> Multimap k1 a -> Multimap k2 a--- ^ mapKeys f s is the multimap obtained by applying f to each key of s.-mapKeys f (Multimap (nk, nv, map)) = Multimap (nk, nv, Map.mapKeys f map)---mapWithKey :: (k -> a -> b) -> Multimap k a -> Multimap k b--- ^ Map a function over all key/value pairs in the map.-mapWithKey f (Multimap (nk, nv, map))- = Multimap (nk, nv, Map.mapWithKey (\k -> P.map (f k)) map)---foldr :: (a -> b -> b) -> b -> Multimap k a -> b--- ^ Fold the values in the map using the given right-associative binary operator.-foldr f e = P.foldr f e . concat . elems---foldl :: (a -> b -> a) -> a -> Multimap k b -> a--- ^ Fold the values in the map using the given left-associative binary operator.-foldl f e = P.foldl f e . concat . elems---foldrWithKey :: (k -> a -> b -> b) -> b -> Multimap k a -> b--- ^ /O(n)./ Fold the keys and values in the map using the given right-associative--- binary operator, taking into account not only the value but also the key.-foldrWithKey f e = P.foldr (uncurry f) e . toList---foldlWithKey :: (a -> k -> b -> a) -> a -> Multimap k b -> a--- ^ /O(n)./ Fold the keys and values in the map using the given left-associative--- binary operator, taking into account not only the value but also the key.-foldlWithKey f e = P.foldl (\a (k,v) -> f a k v) e . toList---elems :: Multimap k a -> [[a]]--- ^ /O(n)./ Return all elements of the multimap in the--- ascending order of their keys.------ A list of lists is returned since a key can have--- multiple values. Use 'concat' to flatten.-elems (Multimap (_, _, map)) = Map.elems map---keys :: Multimap k a -> [k]--- ^ /O(n)./ Return all keys of the multimap in ascending order.-keys (Multimap (_, _, map)) = Map.keys map---keysSet :: Multimap k a -> Set k--- ^ /O(n)./ The set of all keys of the multimap.-keysSet (Multimap (_, _, map)) = Map.keysSet map---assocs :: Multimap k a -> [(k, [a])]--- ^ /O(n)./ Return all key/value pairs in the multimap--- in ascending key order.-assocs (Multimap (_, _, map)) = Map.assocs map---toMap :: Multimap k a -> Map k [a]--- ^ /O(1)./ Return the map of lists.-toMap (Multimap (_, _, theUnderlyingMap)) = theUnderlyingMap---toMapOfSets :: Ord a => Multimap k a -> Map k (Set a)--- ^ /O(k*m*log m) where k is the number of keys and m the--- maximum number of elements associated with a single key/-toMapOfSets (Multimap (_, _, map)) = Map.map Set.fromList map---toList :: Multimap k a -> [(k, a)]--- ^ Return a flattened list of key/value pairs.-toList (Multimap (_, _, map))- = concat $ Map.elems $ Map.mapWithKey (\k -> zip (repeat k)) map---fromList :: Ord k => [(k, a)] -> Multimap k a--- ^ /O(n*log n)/ Create a multimap from a list of key/value pairs.------ > fromList xs == foldr (uncurry insert) empty-fromList = P.foldr (uncurry insert) empty---fromMap :: Map k [a] -> Multimap k a--- ^ Turns a map of lists into a multimap.-fromMap map = Multimap (numKeys, numValues, map)- where- numKeys = fromIntegral $ Map.size map- numValues = fromIntegral $ Map.foldr (\v s -> length v + s) 0 map---findMin :: Multimap k a -> Maybe k--- ^ /O(log n)/ Find the minimal key of the multimap.-findMin (Multimap (_, _, map))- | Map.null map = Nothing- | otherwise = Just $ fst $ Map.findMin map---findMax :: Multimap k a -> Maybe k--- ^ /O(log n)/ Find the maximal key of the multimap.-findMax (Multimap (_, _, map))- | Map.null map = Nothing- | otherwise = Just $ fst $ Map.findMax map---findMinWithValues :: Multimap k a -> Maybe (k, [a])--- ^ /O(log n)/ Find the minimal key and the values associated with it.-findMinWithValues (Multimap (_, _, map))- | Map.null map = Nothing- | otherwise = Just $ Map.findMin map---findMaxWithValues :: Multimap k a -> Maybe (k, [a])--- ^ /O(log n)/ Find the maximal key and the values associated with it.-findMaxWithValues (Multimap (_, _, map))- | Map.null map = Nothing- | otherwise = Just $ Map.findMax map----
+ src/Data/SetMap.hs view
@@ -0,0 +1,160 @@+{-# LANGUAGE Haskell2010+ , DeriveDataTypeable+ #-}+{-# OPTIONS+ -Wall+ -fno-warn-name-shadowing+ #-}++-- | A SetMap allows the association of multiple values with a single key,+-- but there are no duplicates per key.+module Data.SetMap (++ -- * SetMap type+ SetMap,++ -- * Query+ null,+ size,+ numKeys,+ numValues,++ member,+ notMember,+ lookup,++ -- * Operators+ (!),++ -- * Construction+ empty,+ + -- ** Insertion+ insert,++ -- ** Deletion+ delete,++ -- * Traversal+ map,++ -- * Conversion+ elems,+ keys,++ toMap,++ ) where+++import Prelude hiding (lookup, map, null, foldr, foldl)+import qualified Prelude as P++import qualified Data.Set as Set+import Data.Set (Set)++import qualified Data.Map as Map+import Data.Map (Map)++import Data.Word+import Data.Data+++-- | A SetMap with keys @k@ and values @v@.+newtype SetMap k v = SetMap (Word32, Word32, Map k (Set v))+ deriving (Data, Typeable)+++null :: SetMap k a -> Bool+-- ^ /O(1)./ Check whether the multimap is empty or not.+null (SetMap (_, _, m)) = Map.null m+++size :: SetMap k a -> Int+-- ^ /O(1)./ The number of elements in the multimap.+size (SetMap (_, size, _)) = fromIntegral size+++numKeys :: SetMap k a -> Word32+-- ^ /O(1)./ The number of keys in the multimap.+-- +-- As this is a multimap, the number of keys is not+-- necessarily equal to the number of values.+numKeys (SetMap (nk, _, _)) = nk+++numValues :: SetMap k a -> Word32+-- ^ /O(1)./ The number of values in the multimap.+--+-- As this is a multimap, the number of keys is not+-- necessarily equal to the number of values.+numValues (SetMap (_, nv, _)) = nv+++notMember, member :: Ord k => SetMap k a -> k -> Bool+-- | /O(log n)./ Is the key a member of the multimap?+member (SetMap (_, _, map)) key = Map.member key map+-- | /O(log n)./ Is the key not a member of the multimap?+notMember key = not . member key+++(!) :: Ord k => SetMap k a -> k -> Set a+-- ^ As @flip lookup@+(!) = flip lookup+++lookup :: Ord k => k -> SetMap k a -> Set a+-- ^ /O(log n)./ Lookup the value at a key in the map.+--+-- The function will return the corrsponding values as a List, or the+-- empty list if no values are associated witht the given key.+lookup key (SetMap (_, _, map)) = maybe Set.empty id (Map.lookup key map)+++empty :: SetMap k a+-- ^ /O(1)./ The empty multimap.+empty = SetMap (0, 0, Map.empty)+++insert :: (Ord k, Ord a) => k -> a -> SetMap k a -> SetMap k a+-- ^ Insert a new key and value in the map.+insert k v (SetMap (nk, nv, map))+ | Map.member k map =+ let oldSet = map Map.! k+ (nv', newSet) = if v `Set.member` oldSet+ then (nv, oldSet) else (succ nv, v `Set.insert` oldSet)+ in SetMap (nk, nv', Map.insert k newSet map)+ | otherwise = SetMap (succ nk, succ nv, Map.insert k (Set.singleton v) map)+++delete :: Ord k => k -> SetMap k a -> SetMap k a+-- ^ Delete a key and all its values from the map.+delete k m@(SetMap (nk, nv, map)) = case Map.lookup k map of+ Just v -> SetMap (pred nk, nv - fromIntegral (Set.size v), Map.delete k map)+ _ -> m+++map :: (Ord a, Ord b) => (a -> b) -> SetMap k a -> SetMap k b+-- ^ Map a function over all values in the map.+map f (SetMap (nk, nv, map)) = SetMap (nk, nv, Map.map (Set.map f) map)+++elems :: SetMap k a -> [[a]]+-- ^ Return all elements of the multimap in the+-- ascending order of their keys.+--+-- A list of lists is returned since a key can have+-- multiple values. Use 'concat' to flatten.+elems (SetMap (_, _, map)) = P.map (Set.elems) $ Map.elems map+++keys :: SetMap k a -> [k]+-- ^ /O(n)./ Return all keys of the multimap in ascending order.+keys (SetMap (_, _, map)) = Map.keys map+++toMap :: SetMap k a -> Map k (Set a)+-- ^ /O(1)./ Return the map of sets.+toMap (SetMap (_, _, theUnderlyingMap)) = theUnderlyingMap++