multimap-1.2.1/0000755000000000000000000000000012152401621011523 5ustar0000000000000000multimap-1.2.1/LICENSE0000644000000000000000000000200012152401621012520 0ustar0000000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. multimap-1.2.1/multimap.cabal0000644000000000000000000000231712152401621014342 0ustar0000000000000000Name: multimap Version: 1.2.1 Synopsis: A multimap. Description: This is a simple implementation of a multimap, based on "Data.Map". . [@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@. . [@v1.2.1@] Fixed typos in the documentation. License: MIT License-File: LICENSE Author: Julian Fleischer Maintainer: Julian Fleischer Build-Type: Simple Cabal-Version: >= 1.6 Category: Data Structures Stability: provisional Homepage: http://hub.darcs.net/scravy/multimap Source-Repository head type: darcs location: hub.darcs.net:multimap Library Exposed-Modules: Data.MultiMap , Data.SetMap Build-Depends: base >= 3 && < 5, containers Hs-Source-Dirs: src multimap-1.2.1/Setup.hs0000644000000000000000000000006012152401621013153 0ustar0000000000000000import Distribution.Simple main = defaultMain multimap-1.2.1/src/0000755000000000000000000000000012152401621012312 5ustar0000000000000000multimap-1.2.1/src/Data/0000755000000000000000000000000012152401621013163 5ustar0000000000000000multimap-1.2.1/src/Data/MultiMap.hs0000644000000000000000000001731112152401621015252 0ustar0000000000000000{-# LANGUAGE Haskell2010 , DeriveDataTypeable #-} {-# OPTIONS -Wall -fno-warn-name-shadowing #-} -- | -- Module : Data.MultiMap -- Copyright : (c) Julian Fleischer 2013 -- License : MIT (See LICENSE file in cabal package) -- -- Maintainer : julian.fleischer@fu-berlin.de -- Portability : non-portable (DeriveDataTypeable) -- -- 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 multimap-1.2.1/src/Data/SetMap.hs0000644000000000000000000001000212152401621014701 0ustar0000000000000000{-# LANGUAGE Haskell2010 , DeriveDataTypeable #-} {-# OPTIONS -Wall -fno-warn-name-shadowing #-} -- Module : Data.SetMap -- Copyright : (c) Julian Fleischer 2013 -- License : MIT (See LICENSE file in cabal package) -- -- Maintainer : julian.fleischer@fu-berlin.de -- Portability : non-portable (DeriveDataTypeable) -- -- 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