packages feed

multi-containers 0.1.1 → 0.2

raw patch · 17 files changed

+2854/−2365 lines, 17 files

Files

ChangeLog.md view
@@ -1,5 +1,10 @@ # Changelog for multi-containers +## 0.2++- Add Internal modules that export data constructors+- Add conversion functions between Multimap and SetMultimap+ ## 0.1.1  - Add min/max functions for `Data.Multimap` and `Data.Multimap.Set`.
LICENSE view
@@ -1,4 +1,4 @@-Copyright Ziyang Liu (c) 2019-2020.+Copyright Ziyang Liu (c) 2019-2021.  All rights reserved. 
multi-containers.cabal view
@@ -1,7 +1,7 @@ cabal-version:  2.4  name:           multi-containers-version:        0.1.1+version:        0.2 synopsis:       A few multimap variants. description:    A library that provides a few multimap variants. category:       Data Structures@@ -13,7 +13,7 @@ license:        BSD-3-Clause license-file:   LICENSE build-type:     Simple-tested-with:    GHC==8.10.1, GHC==8.8.2, GHC==8.6.5, GHC==8.4.4+tested-with:    GHC==9.0.1, GHC==8.10.4, GHC==8.8.4, GHC==8.6.5  extra-source-files:     ChangeLog.md@@ -26,8 +26,12 @@ library   exposed-modules:       Data.Multimap+      Data.Multimap.Internal       Data.Multimap.Set+      Data.Multimap.Set.Internal       Data.Multimap.Table+      Data.Multimap.Table.Internal+      Data.Multimap.Conversions   other-modules:       Paths_multi_containers   autogen-modules:@@ -44,9 +48,12 @@   type: exitcode-stdio-1.0   main-is: Main.hs   other-modules:-      Data.Multimap.SetSpec-      Data.Multimap.TableSpec       Data.MultimapSpec+      Data.Multimap.InternalSpec+      Data.Multimap.SetSpec+      Data.Multimap.Set.InternalSpec+      Data.Multimap.Table.InternalSpec+      Data.Multimap.ConversionsSpec       Paths_multi_containers   autogen-modules:       Paths_multi_containers
src/Data/Multimap.hs view
@@ -1,7 +1,3 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeFamilies #-}- ----------------------------------------------------------------------------- -- | -- Module      :  Data.Multimap@@ -124,6 +120,11 @@   -- ** Maps   , toMap +  -- ** SetMultimaps+  , fromSetMultimapAsc+  , fromSetMultimapDesc+  , toSetMultimap+   -- * Filter   , filter   , filterWithKey@@ -145,660 +146,21 @@   , lookupGE   ) where -import           Control.Arrow ((&&&))-import           Control.Monad (join)-import qualified Control.Monad as List (filterM)-import           Data.Data (Data)-import qualified Data.Either as Either-import qualified Data.Foldable as Foldable-import           Data.Functor.Classes-import qualified Data.List as List-import           Data.List.NonEmpty (NonEmpty(..), (<|), nonEmpty)-import qualified Data.List.NonEmpty as Nel-import           Data.Map.Lazy (Map)-import qualified Data.Map.Lazy as Map-import qualified Data.Maybe as Maybe-import           Data.Set (Set)-+import Data.Multimap.Conversions+import Data.Multimap.Internal+import Data.Multimap.Set.Internal (SetMultimap) import Prelude hiding (filter, foldl, foldr, lookup, map, null) -infixl 9 !--type Size = Int--newtype Multimap k a = Multimap (Map k (NonEmpty a), Size)-  deriving (Eq, Ord, Data)--instance Eq k => Eq1 (Multimap k) where-  liftEq = liftEq2 (==)--instance Eq2 Multimap where-  liftEq2 eqk eqv m n =-    Map.size (toMap m) == Map.size (toMap n)-      && liftEq (liftEq2 eqk eqv) (toList m) (toList n)--instance Ord k => Ord1 (Multimap k) where-  liftCompare = liftCompare2 compare--instance Ord2 Multimap where-  liftCompare2 cmpk cmpv m n =-      liftCompare (liftCompare2 cmpk cmpv) (toList m) (toList n)--instance (Show k, Show a) => Show (Multimap k a) where-  showsPrec d m = showParen (d > 10) $-    showString "fromList " . shows (toList m)--instance Show k => Show1 (Multimap k) where-  liftShowsPrec = liftShowsPrec2 showsPrec showList--instance Show2 Multimap where-  liftShowsPrec2 spk slk spv slv d m =-      showsUnaryWith (liftShowsPrec sp sl) "fromList" d (toList m)-    where-      sp = liftShowsPrec2 spk slk spv slv-      sl = liftShowList2 spk slk spv slv--instance (Ord k, Read k, Read e) => Read (Multimap k e) where-  readsPrec p = readParen (p > 10) $ \ r -> do-    ("fromList",s) <- lex r-    (xs,t) <- reads s-    pure (fromList xs,t)--instance (Ord k, Read k) => Read1 (Multimap k) where-  liftReadsPrec rp rl = readsData $-      readsUnaryWith (liftReadsPrec rp' rl') "fromList" fromList-    where-      rp' = liftReadsPrec rp rl-      rl' = liftReadList rp rl--instance Functor (Multimap k) where-  fmap = map--instance Foldable.Foldable (Multimap k) where-  foldMap = foldMapWithKey . const-  {-# INLINE foldMap #-}--instance Traversable (Multimap k) where-  traverse = traverseWithKey . const-  {-# INLINE traverse #-}--instance (Ord k) => Semigroup (Multimap k a) where-  (<>) = union--instance (Ord k) => Monoid (Multimap k a) where-  mempty = empty-  mappend = (<>)------------------------------------------------------------------------------------ | /O(1)/. The empty multimap.------ > size empty === 0-empty :: Multimap k a-empty = Multimap (Map.empty, 0)---- | /O(1)/. A multimap with a single element.------ > singleton 1 'a' === fromList [(1, 'a')]--- > size (singleton 1 'a') === 1-singleton :: k -> a -> Multimap k a-singleton k a = Multimap (Map.singleton k (pure a), 1)---- | /O(n*log n)/ where /n/ is the length of the input list.---  Build a multimap from a list of key\/value pairs.------ > fromList ([] :: [(Int, Char)]) === empty-fromList :: Ord k => [(k, a)] -> Multimap k a-fromList = Foldable.foldr (uncurry insert) empty---- | /O(1)/.-fromMap :: Map k (NonEmpty a) -> Multimap k a-fromMap m = Multimap (m, sum (fmap length m))---- | /O(k)/. A key is retained only if it is associated with a--- non-empty list of values.------ > fromMap' (Map.fromList [(1, "ab"), (2, ""), (3, "c")]) === fromList [(1, 'a'), (1, 'b'), (3, 'c')]-fromMap' :: Map k [a] -> Multimap k a-fromMap' m = Multimap (Map.mapMaybe nonEmpty m, sum (fmap length m))------------------------------------------------------------------------------------ | /O(log k)/. If the key exists in the multimap, the new value will be--- prepended to the list of values for the key.------ > insert 1 'a' empty === singleton 1 'a'--- > insert 1 'a' (fromList [(2, 'b'), (2, 'c')]) === fromList [(1, 'a'), (2, 'b'), (2, 'c')]--- > insert 1 'a' (fromList [(1, 'b'), (2, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]-insert :: Ord k => k -> a -> Multimap k a -> Multimap k a-insert k a (Multimap (m, _)) = fromMap (Map.alter f k m)-  where-    f (Just as) = Just (a <| as)-    f Nothing = Just (pure a)---- | /O(log k)/. Delete a key and all its values from the map.------ > delete 1 (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === singleton 2 'c'-delete :: Ord k => k -> Multimap k a -> Multimap k a-delete = update' (const [])---- | /O(m*log k)/. Remove the first--- occurrence of the value associated with the key, if exists.------ > deleteWithValue 1 'c' (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]--- > deleteWithValue 1 'c' (fromList [(1, 'a'), (1, 'b'), (2, 'c'), (1, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]--- > deleteWithValue 1 'c' (fromList [(2, 'c'), (1, 'c')]) === singleton 2 'c'-deleteWithValue :: (Ord k, Eq a) => k -> a -> Multimap k a -> Multimap k a-deleteWithValue k a = update' (List.delete a . Nel.toList) k---- | /O(log k)/. Remove the first--- value associated with the key. If the key is associated with a single value,--- the key will be removed from the multimap.------ > deleteOne 1 (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === fromList [(1, 'b'), (2, 'c')]--- > deleteOne 1 (fromList [(2, 'c'), (1, 'c')]) === singleton 2 'c'-deleteOne :: Ord k => k -> Multimap k a -> Multimap k a-deleteOne = update' Nel.tail---- | /O(m*log k)/, assuming the function @a -> a@ takes /O(1)/.--- Update values at a specific key, if exists.------ > adjust ("new " ++) 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(1,"new b"),(2,"c")]-adjust :: Ord k => (a -> a) -> k -> Multimap k a -> Multimap k a-adjust = adjustWithKey . const---- | /O(m*log k)/, assuming the function @k -> a -> a@ takes /O(1)/.--- Update values at a specific key, if exists.------ > adjustWithKey (\k x -> show k ++ ":new " ++ x) 1 (fromList [(1,"a"),(1,"b"),(2,"c")])--- >   === fromList [(1,"1:new a"),(1,"1:new b"),(2,"c")]-adjustWithKey :: Ord k => (k -> a -> a) -> k -> Multimap k a -> Multimap k a-adjustWithKey f k (Multimap (m, sz)) = Multimap (m', sz)-  where-    m' = Map.adjustWithKey (fmap . f) k m---- | /O(m*log k)/, assuming the function @a -> 'Maybe' a@ takes /O(1)/.--- The expression (@'update' f k map@) updates the values at key @k@, if--- exists. If @f@ returns 'Nothing' for a value, the value is deleted.------ > let f x = if x == "a" then Just "new a" else Nothing in do--- >   update f 1 (fromList [(1,"a"),(1, "b"),(2,"c")]) === fromList [(1,"new a"),(2, "c")]--- >   update f 1 (fromList [(1,"b"),(1, "b"),(2,"c")]) === singleton 2 "c"-update :: Ord k => (a -> Maybe a) -> k -> Multimap k a -> Multimap k a-update = updateWithKey . const---- | /O(log k)/, assuming the function @'NonEmpty' a -> [a]@ takes /O(1)/.--- The expression (@'update' f k map@) updates the values at key @k@, if--- exists. If @f@ returns 'Nothing', the key is deleted.------ > update' NonEmpty.tail 1 (fromList [(1, "a"), (1, "b"), (2, "c")]) === fromList [(1, "b"), (2, "c")]--- > update' NonEmpty.tail 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"-update' :: Ord k => (NonEmpty a -> [a]) -> k -> Multimap k a -> Multimap k a-update' = updateWithKey' . const---- | /O(m*log k)/, assuming the function @k -> a -> 'Maybe' a@ takes /O(1)/.--- The expression (@'updateWithKey' f k map@) updates the values at key @k@, if--- exists. If @f@ returns 'Nothing' for a value, the value is deleted.------ > let f k x = if x == "a" then Just (show k ++ ":new a") else Nothing in do--- >   updateWithKey f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"1:new a"),(2,"c")]--- >   updateWithKey f 1 (fromList [(1,"b"),(1,"b"),(2,"c")]) === singleton 2 "c"-updateWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Multimap k a -> Multimap k a-updateWithKey f = alterWithKey (Maybe.mapMaybe . f)---- | /O(log k)/, assuming the function @k -> 'NonEmpty' a -> [a]@ takes /O(1)/.--- The expression (@'update' f k map@) updates the values at key @k@, if--- exists. If @f@ returns 'Nothing', the key is deleted.------ > let f k xs = if NonEmpty.length xs == 1 then (show k : NonEmpty.toList xs) else [] in do--- >   updateWithKey' f 1 (fromList [(1, "a"), (1, "b"), (2, "c")]) === singleton 2 "c"--- >   updateWithKey' f 1 (fromList [(1, "a"), (2, "b"), (2, "c")]) === fromList [(1, "1"), (1, "a"), (2, "b"), (2, "c")]-updateWithKey' :: Ord k => (k -> NonEmpty a -> [a]) -> k -> Multimap k a -> Multimap k a-updateWithKey' f = alterWithKey g-  where-    g _ [] = []-    g k (a:as) = f k (a :| as)---- | /O(log k)/, assuming the function @[a] -> [a]@ takes /O(1)/.--- The expression (@'alter' f k map@) alters the values at k, if exists.------ > let (f, g) = (const [], ('c':)) in do--- >   alter f 1 (fromList [(1, 'a'), (2, 'b')]) === singleton 2 'b'--- >   alter f 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b')]--- >   alter g 1 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'c'), (1, 'a'), (2, 'b')]--- >   alter g 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b'), (3, 'c')]-alter :: Ord k => ([a] -> [a]) -> k -> Multimap k a -> Multimap k a-alter = alterWithKey . const---- | /O(log k)/, assuming the function @k -> [a] -> [a]@ takes /O(1)/.--- The expression (@'alterWithKey' f k map@) alters the values at k, if exists.------ > let (f, g) = (const (const []), (:) . show) in do--- >   alterWithKey f 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"--- >   alterWithKey f 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b")]--- >   alterWithKey g 1 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "1"), (1, "a"), (2, "b")]--- >   alterWithKey g 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b"), (3, "3")]-alterWithKey :: Ord k => (k -> [a] -> [a]) -> k -> Multimap k a -> Multimap k a-alterWithKey f k mm@(Multimap (m, _)) = case nonEmpty (f k (mm ! k)) of-    Just as' -> fromMap (Map.insert k as' m)-    Nothing -> fromMap (Map.delete k m)------------------------------------------------------------------------------------ | /O(log k)/. Lookup the values at a key in the map. It returns an empty--- list if the key is not in the map.-lookup :: Ord k => k -> Multimap k a -> [a]-lookup k (Multimap (m, _)) = maybe [] Nel.toList (Map.lookup k m)---- | /O(log k)/. Lookup the values at a key in the map. It returns an empty--- list if the key is not in the map.------ > fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 3 === "ac"--- > fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 2 === []-(!) :: Ord k => Multimap k a -> k -> [a]-(!) = flip lookup---- | /O(log k)/. Is the key a member of the map?------ A key is a member of the map if and only if there is at least one value--- associated with it.------ > member 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === True--- > member 1 (deleteOne 1 (fromList [(2, 'c'), (1, 'c')])) === False-member :: Ord k => k -> Multimap k a -> Bool-member k (Multimap (m, _)) = Map.member k m---- | /O(log k)/. Is the key not a member of the map?------ A key is a member of the map if and only if there is at least one value--- associated with it.------ > notMember 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === False--- > notMember 1 (deleteOne 1 (fromList [(2, 'c'), (1, 'c')])) === True-notMember :: Ord k => k -> Multimap k a -> Bool-notMember k = not . member k---- | /O(1)/. Is the multimap empty?------ > Data.Multimap.null empty === True--- > Data.Multimap.null (singleton 1 'a') === False-null :: Multimap k a -> Bool-null (Multimap (m, _)) = Map.null m---- | /O(1)/. Is the multimap non-empty?------ > notNull empty === False--- > notNull (singleton 1 'a') === True-notNull :: Multimap k a -> Bool-notNull = not . null---- | The total number of values for all keys.------ @size@ is evaluated lazily. Forcing the size for the first time takes up to--- /O(n)/ and subsequent forces take /O(1)/.------ > size empty === 0--- > size (singleton 1 'a') === 1--- > size (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === 3-size :: Multimap k a -> Int-size (Multimap (_, sz)) = sz------------------------------------------------------------------------------------ | Union two multimaps, concatenating values for duplicate keys.------ > union (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b')])--- >   === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c'),(2,'b')]-union :: Ord k => Multimap k a -> Multimap k a -> Multimap k a-union (Multimap (m1, _)) (Multimap (m2, _)) =-  fromMap (Map.unionWith (<>) m1 m2)---- | Union a number of multimaps, concatenating values for duplicate keys.------ > unions [fromList [(1,'a'),(2,'b'),(2,'c')], fromList [(1,'d'),(2,'b')]]--- >   === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c'),(2,'b')]-unions :: (Foldable f, Ord k) => f (Multimap k a) -> Multimap k a-unions = Foldable.foldr union empty---- | Difference of two multimaps.------ If a key exists in the first multimap but not the second, it remains--- unchanged in the result. If a key exists in both multimaps, a list--- difference is performed on their values, i.e., the first occurrence--- of each value in the second multimap is removed from the--- first multimap.------ > difference (fromList [(1,'a'),(2,'b'),(2,'c'),(2,'b')]) (fromList [(1,'d'),(2,'b'),(2,'a')])--- >   === fromList [(1,'a'), (2,'c'), (2,'b')]-difference :: (Ord k, Eq a) => Multimap k a -> Multimap k a -> Multimap k a-difference (Multimap (m1, _)) (Multimap (m2, _)) = fromMap $-  Map.differenceWith (\xs ys -> nonEmpty (Nel.toList xs List.\\ Nel.toList ys)) m1 m2------------------------------------------------------------------------------------ | /O(n)/, assuming the function @a -> b@ takes /O(1)/.--- Map a function over all values in the map.------ > Data.Multimap.map (++ "x") (fromList [(1,"a"),(1,"a"),(2,"b")]) === fromList [(1,"ax"),(1,"ax"),(2,"bx")]-map :: (a -> b) -> Multimap k a -> Multimap k b-map = mapWithKey . const---- | /O(n)/, assuming the function @k -> a -> b@ takes /O(1)/.--- Map a function over all key\/value pairs in the map.------ > mapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1,"a"),(1,"a"),(2,"b")]) === fromList [(1,"1:a"),(1,"1:a"),(2,"2:b")]-mapWithKey :: (k -> a -> b) -> Multimap k a -> Multimap k b-mapWithKey f (Multimap (m, sz)) = Multimap (Map.mapWithKey (fmap . f) m, sz)---- | Traverse key\/value pairs and collect the results.------ > let f k a = if odd k then Just (succ a) else Nothing in do--- >   traverseWithKey f (fromList [(1, 'a'), (1, 'b'), (3, 'b'), (3, 'c')]) === Just (fromList [(1, 'b'), (1, 'c'), (3, 'c'), (3, 'd')])--- >   traverseWithKey f (fromList [(1, 'a'), (1, 'b'), (2, 'b')]) === Nothing-traverseWithKey :: Applicative t => (k -> a -> t b) -> Multimap k a -> t (Multimap k b)-traverseWithKey f (Multimap (m, _)) =-  fromMap <$> Map.traverseWithKey (traverse . f) m---- | Traverse key\/value pairs and collect the 'Just' results.-traverseMaybeWithKey :: Applicative t => (k -> a -> t (Maybe b)) -> Multimap k a -> t (Multimap k b)-traverseMaybeWithKey f (Multimap (m, _)) =-    fromMap <$> Map.traverseMaybeWithKey f' m-  where-    f' k = fmap (nonEmpty . Maybe.catMaybes) . traverse (f k) . Nel.toList------------------------------------------------------------------------------------ | /O(n)/. Fold the values in the map using the given right-associative--- binary operator.------ > Data.Multimap.foldr ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-foldr :: (a -> b -> b) -> b -> Multimap k a -> b-foldr = foldrWithKey . const---- | /O(n)/. Fold the values in the map using the given left-associative--- binary operator.------ > Data.Multimap.foldl (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-foldl :: (a -> b -> a) -> a -> Multimap k b -> a-foldl = foldlWithKey . (const .)---- | /O(n)/. Fold the key\/value pairs in the map using the given--- right-associative binary operator.------ > foldrWithKey (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-foldrWithKey :: (k -> a -> b -> b) -> b -> Multimap k a -> b-foldrWithKey f b (Multimap (m, _)) = Map.foldrWithKey f' b m-  where-    f' = flip . Foldable.foldr . f---- | /O(n)/. Fold the key\/value pairs in the map using the given--- left-associative binary operator.------ > foldlWithKey (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-foldlWithKey :: (a -> k -> b -> a) -> a -> Multimap k b -> a-foldlWithKey f a (Multimap (m, _)) = Map.foldlWithKey f' a m-  where-    f' = flip (Foldable.foldl . flip f)---- | /O(n)/. A strict version of 'foldr'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > Data.Multimap.foldr' ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-foldr' :: (a -> b -> b) -> b -> Multimap k a -> b-foldr' = foldrWithKey' . const---- | /O(n)/. A strict version of 'foldl'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > Data.Multimap.foldl' (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-foldl' :: (a -> b -> a) -> a -> Multimap k b -> a-foldl' = foldlWithKey' . (const .)---- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > foldrWithKey' (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-foldrWithKey' :: (k -> a -> b -> b) -> b -> Multimap k a -> b-foldrWithKey' f b (Multimap (m, _)) = Map.foldrWithKey' f' b m-  where-    f' = flip . Foldable.foldr . f---- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > foldlWithKey' (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-foldlWithKey' :: (a -> k -> b -> a) -> a -> Multimap k b -> a-foldlWithKey' f a (Multimap (m, _)) = Map.foldlWithKey' f' a m-  where-    f' = flip (Foldable.foldl' . flip f)---- | /O(n)/. Fold the key\/value pairs in the map using the given monoid.------ > foldMapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1, "a"), (1, "a"), (2, "b")]) === "1:a1:a2:b"-foldMapWithKey :: Monoid m => (k -> a -> m) -> Multimap k a -> m-foldMapWithKey f (Multimap (m, _)) = Map.foldMapWithKey f' m-  where-    f' = Foldable.foldMap . f------------------------------------------------------------------------------------ | /O(n)/. Return all elements of the multimap in ascending order of--- their keys.------ > elems (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === "bbac"--- > elems (empty :: Multimap Int Char) === []-elems :: Multimap k a -> [a]-elems (Multimap (m, _)) = Map.elems m >>= Nel.toList---- | /O(k)/. Return all keys of the multimap in ascending order.------ > keys (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === [1,2,3]--- > keys (empty :: Multimap Int Char) === []-keys :: Multimap k a -> [k]-keys (Multimap (m, _)) = Map.keys m---- | /O(k)/. The set of all keys of the multimap.------ > keysSet (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === Set.fromList [1,2,3]--- > keysSet (empty :: Multimap Int Char) === Set.empty-keysSet :: Multimap k a -> Set k-keysSet (Multimap (m, _)) = Map.keysSet m---- | An alias for 'toAscList'.------ > assocs (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]-assocs :: Multimap k a -> [(k, a)]-assocs = toAscList---- | Convert the multimap into a list of key/value pairs.------ > toList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]-toList :: Multimap k a -> [(k, a)]-toList = toAscList---- | Convert the multimap into a list of key/value pairs in ascending--- order of keys.------ > toAscList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]-toAscList :: Multimap k a -> [(k, a)]-toAscList (Multimap (m, _)) =-  Map.toAscList m >>= uncurry (\k -> fmap (k,) . Nel.toList)---- | Convert the multimap into a list of key/value pairs in descending--- order of keys.------ > toDescList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(3,'c'),(2,'a'),(1,'b'),(1,'a')]-toDescList :: Multimap k a -> [(k, a)]-toDescList (Multimap (m, _)) =-  Map.toDescList m >>= uncurry (\k -> fmap (k,) . Nel.toList)---- | Convert the multimap into a list of key/value pairs, in a--- breadth-first manner, in ascending order of keys.------ > toAscListBF (fromList [("Foo",1),("Foo",2),("Foo",3),("Bar",4),("Bar",5),("Baz",6)])--- >   === [("Bar",4),("Baz",6),("Foo",1),("Bar",5),("Foo",2),("Foo",3)]-toAscListBF :: Multimap k a -> [(k, a)]-toAscListBF (Multimap (m, _)) =-  join-  . List.transpose-  . fmap (uncurry (\k -> fmap (k,) . Nel.toList))-  $ Map.toAscList m---- | Convert the multimap into a list of key/value pairs, in a--- breadth-first manner, in descending order of keys.------ > toDescListBF (fromList [("Foo",1),("Foo",2),("Foo",3),("Bar",4),("Bar",5),("Baz",6)])--- >   === [("Foo",1),("Baz",6),("Bar",4),("Foo",2),("Bar",5),("Foo",3)]-toDescListBF :: Multimap k a -> [(k, a)]-toDescListBF (Multimap (m, _)) =-  join-  . List.transpose-  . fmap (uncurry (\k -> fmap (k,) . Nel.toList))-  $ Map.toDescList m---- | /O(1)/. Convert the multimap into a regular map.-toMap :: Multimap k a -> Map k (NonEmpty a)-toMap (Multimap (m, _)) = m------------------------------------------------------------------------------------ | /O(n)/, assuming the predicate function takes /O(1)/.--- Retain all values that satisfy the predicate.------ > Data.Multimap.filter (> 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 1 'b'--- > Data.Multimap.filter (< 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === empty-filter :: (a -> Bool) -> Multimap k a -> Multimap k a-filter = filterWithKey . const---- | /O(k)/, assuming the predicate function takes /O(1)/.--- Retain all keys that satisfy the predicate.------ > filterKey even (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 2 'a'-filterKey :: (k -> Bool) -> Multimap k a -> Multimap k a-filterKey p (Multimap (m, _)) = fromMap m'-  where-    m' = Map.filterWithKey (const . p) m---- | /O(n)/, assuming the predicate function takes /O(1)/.--- Retain all key\/value pairs that satisfy the predicate.------ > filterWithKey (\k a -> even k && a > 'a') (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'b')]) === singleton 2 'b'-filterWithKey :: (k -> a -> Bool) -> Multimap k a -> Multimap k a-filterWithKey p (Multimap (m, _)) = fromMap m'-  where-    m' = Map.mapMaybeWithKey (\k -> nonEmpty . Nel.filter (p k)) m---- | Generalized 'filter'.------ > let f a | a > 'b' = Just True--- >         | a < 'b' = Just False--- >         | a == 'b' = Nothing--- >  in do--- >    filterM f (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'c')]) === Nothing--- >    filterM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Just (fromList [(1,'c'),(2,'c')])-filterM :: (Ord k, Applicative t) => (a -> t Bool) -> Multimap k a -> t (Multimap k a)-filterM = filterWithKeyM . const---- | Generalized 'filterWithKey'.------ > let f k a | even k && a > 'b' = Just True--- >           | odd k && a < 'b' = Just False--- >           | otherwise = Nothing--- >  in do--- >    filterWithKeyM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Nothing--- >    filterWithKeyM f (fromList [(1,'a'),(1,'a'),(2,'c'),(2,'c')]) === Just (fromList [(2,'c'),(2,'c')])-filterWithKeyM :: (Ord k, Applicative t) => (k -> a -> t Bool) -> Multimap k a -> t (Multimap k a)-filterWithKeyM f = fmap fromList . List.filterM (uncurry f) . toList---- | /O(n)/, assuming the function @a -> 'Maybe' b@ takes /O(1)/.--- Map values and collect the 'Just' results.------ > mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])--- >   === fromList [(1,"new a"),(2,"new a")]-mapMaybe :: (a -> Maybe b) -> Multimap k a -> Multimap k b-mapMaybe = mapMaybeWithKey . const---- | /O(n)/, assuming the function @k -> a -> 'Maybe' b@ takes /O(1)/.--- Map key\/value pairs and collect the 'Just' results.------ > mapMaybeWithKey (\k a -> if k > 1 && a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])--- >   === singleton 2 "new a"-mapMaybeWithKey :: (k -> a -> Maybe b) -> Multimap k a -> Multimap k b-mapMaybeWithKey f (Multimap (m, _)) = fromMap $-  Map.mapMaybeWithKey (\k -> nonEmpty . Maybe.mapMaybe (f k) . Nel.toList) m---- | /O(n)/, assuming the function @a -> 'Either' b c@ takes /O(1)/.--- Map values and separate the 'Left' and 'Right' results.------ > mapEither (\a -> if a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])--- >   === (fromList [(1,'a'),(2,'a')],fromList [(1,'c'),(2,'c')])-mapEither :: (a -> Either b c) -> Multimap k a -> (Multimap k b, Multimap k c)-mapEither = mapEitherWithKey . const---- | /O(n)/, assuming the function @k -> a -> 'Either' b c@ takes /O(1)/.--- Map key\/value pairs and separate the 'Left' and 'Right' results.------ > mapEitherWithKey (\k a -> if even k && a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])--- >   === (fromList [(2,'a')],fromList [(1,'a'),(1,'c'),(2,'c')])-mapEitherWithKey :: (k -> a -> Either b c) -> Multimap k a -> (Multimap k b, Multimap k c)-mapEitherWithKey f (Multimap (m, _)) =-    (fromMap' . Map.mapWithKey (const fst) &&& fromMap' . Map.mapWithKey (const snd))-      $ Map.mapWithKey g m-  where-    g k as = Either.partitionEithers $ fmap (f k) (Nel.toList as)------------------------------------------------------------------------------------ | /O(log n)/. Return the smallest key and the associated values. Returns 'Nothing'--- if the map is empty.------ > lookupMin (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (1, NonEmpty.fromList "ac")--- > lookupMin (empty :: Multimap Int Char) === Nothing-lookupMin :: Multimap k a -> Maybe (k, NonEmpty a)-lookupMin (Multimap (m, _)) = Map.lookupMin m---- | /O(log n)/. Return the largest key and the associated values. Returns 'Nothing'--- if the map is empty.------ > lookupMax (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (2, NonEmpty.fromList "c")--- > lookupMax (empty :: Multimap Int Char) === Nothing-lookupMax :: Multimap k a -> Maybe (k, NonEmpty a)-lookupMax (Multimap (m, _)) = Map.lookupMax m---- | /O(log n)/. Return the largest key smaller than the given one, and the associated--- values, if exist.------ > lookupLT 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing--- > lookupLT 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")-lookupLT :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)-lookupLT k (Multimap (m, _)) = Map.lookupLT k m---- | /O(log n)/. Return the smallest key larger than the given one, and the associated--- values, if exist.------ > lookupGT 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing--- > lookupGT 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")-lookupGT :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)-lookupGT k (Multimap (m, _)) = Map.lookupGT k m---- | /O(log n)/. Return the largest key smaller than or equal to the given one, and the associated--- values, if exist.+-- | Convert a t'Data.Multimap.Set.SetMultimap' to a t'Data.Multimap.Multimap' where the values of each key+-- are in ascending order. ----- > lookupLE 0 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing--- > lookupLE 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (1, NonEmpty.fromList "a")--- > lookupLE 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")-lookupLE :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)-lookupLE k (Multimap (m, _)) = Map.lookupLE k m+-- > fromSetMultimapAsc (Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.fromList [(1,'a'),(1,'b'),(2,'c')]+fromSetMultimapAsc :: SetMultimap k a -> Multimap k a+fromSetMultimapAsc = toMultimapAsc --- | /O(log n)/. Return the smallest key larger than or equal to the given one, and the associated--- values, if exist.+-- | Convert a t'Data.Multimap.Set.SetMultimap' to a t'Data.Multimap.Multimap' where the values of each key+-- are in descending order. ----- > lookupGE 6 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing--- > lookupGE 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (5, NonEmpty.fromList "c")--- > lookupGE 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")-lookupGE :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)-lookupGE k (Multimap (m, _)) = Map.lookupGE k m+-- > fromSetMultimapDesc (Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.fromList [(1,'b'),(1,'a'),(2,'c')]+fromSetMultimapDesc :: SetMultimap k a -> Multimap k a+fromSetMultimapDesc = toMultimapDesc
+ src/Data/Multimap/Conversions.hs view
@@ -0,0 +1,43 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Data.Multimap.Conversions+-- Maintainer  :  Ziyang Liu <free@cofree.io>+--+-- Conversions between 'Multimap' and 'SetMultimap'.+module Data.Multimap.Conversions (+  toMultimapAsc+  , toMultimapDesc+  , toSetMultimap+) where++import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Map as Map+import Data.Multimap.Internal (Multimap (..))+import Data.Multimap.Set.Internal (SetMultimap (..))+import qualified Data.Set as Set++-- | Convert a t'Data.Multimap.Set.SetMultimap' to a t'Data.Multimap.Multimap' where the values of each key+-- are in ascending order.+--+-- > toMultimapAsc (Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.fromList [(1,'a'),(1,'b'),(2,'c')]+toMultimapAsc :: SetMultimap k a -> Multimap k a+toMultimapAsc (SetMultimap (m, sz)) = Multimap (m', sz)+  where+    m' = Map.mapMaybe (NonEmpty.nonEmpty . Set.toAscList) m++-- | Convert a t'Data.Multimap.Set.SetMultimap' to a t'Data.Multimap.Multimap' where the values of each key+-- are in descending order.+--+-- > toMultimapDesc (Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.fromList [(1,'b'),(1,'a'),(2,'c')]+toMultimapDesc :: SetMultimap k a -> Multimap k a+toMultimapDesc (SetMultimap (m, sz)) = Multimap (m', sz)+  where+    m' = Map.mapMaybe (NonEmpty.nonEmpty . Set.toDescList) m++-- | Convert a t'Data.Multimap.Multimap' to a t'Data.Multimap.Set.SetMultimap'.+--+-- > toSetMultimap (Data.Multimap.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]+toSetMultimap :: Ord a => Multimap k a -> SetMultimap k a+toSetMultimap (Multimap (m, sz)) = SetMultimap (m', sz)+  where+    m' = Map.map (Set.fromList . NonEmpty.toList) m
+ src/Data/Multimap/Internal.hs view
@@ -0,0 +1,775 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  Data.Multimap.Internal+-- Maintainer  :  Ziyang Liu <free@cofree.io>+--+module Data.Multimap.Internal (+  -- * Multimap type+  Multimap (..)+  , Size++  -- * Construction+  , empty+  , singleton+  , fromMap+  , fromMap'++  -- ** From Unordered Lists+  , fromList++  -- * Insertion+  , insert++  -- * Deletion\/Update+  , delete+  , deleteWithValue+  , deleteOne+  , adjust+  , adjustWithKey+  , update+  , update'+  , updateWithKey+  , updateWithKey'+  , alter+  , alterWithKey++  -- * Query+  -- ** Lookup+  , lookup+  , (!)+  , member+  , notMember++  -- ** Size+  , null+  , notNull+  , size++  -- * Combine+  -- ** Union+  , union+  , unions++  -- ** Difference+  , difference++  -- * Traversal+  -- ** Map+  , map+  , mapWithKey+  , traverseWithKey+  , traverseMaybeWithKey++  -- ** Folds+  , foldr+  , foldl+  , foldrWithKey+  , foldlWithKey+  , foldMapWithKey++  -- ** Strict Folds+  , foldr'+  , foldl'+  , foldrWithKey'+  , foldlWithKey'++  -- * Conversion+  , elems+  , keys+  , assocs+  , keysSet++  -- ** Lists+  , toList++  -- ** Ordered lists+  , toAscList+  , toDescList+  , toAscListBF+  , toDescListBF++  -- ** Maps+  , toMap++  -- * Filter+  , filter+  , filterWithKey+  , filterKey+  , filterM+  , filterWithKeyM++  , mapMaybe+  , mapMaybeWithKey+  , mapEither+  , mapEitherWithKey++  -- * Min\/Max+  , lookupMin+  , lookupMax+  , lookupLT+  , lookupGT+  , lookupLE+  , lookupGE+  ) where++import           Control.Arrow ((&&&))+import           Control.Monad (join)+import qualified Control.Monad as List (filterM)+import           Data.Data (Data)+import qualified Data.Either as Either+import qualified Data.Foldable as Foldable+import           Data.Functor.Classes+import qualified Data.List as List+import           Data.List.NonEmpty (NonEmpty(..), (<|), nonEmpty)+import qualified Data.List.NonEmpty as Nel+import           Data.Map.Lazy (Map)+import qualified Data.Map.Lazy as Map+import qualified Data.Maybe as Maybe+import           Data.Set (Set)++import Prelude hiding (filter, foldl, foldr, lookup, map, null)++infixl 9 !++type Size = Int++newtype Multimap k a = Multimap (Map k (NonEmpty a), Size)+  deriving (Eq, Ord, Data)++instance Eq k => Eq1 (Multimap k) where+  liftEq = liftEq2 (==)++instance Eq2 Multimap where+  liftEq2 eqk eqv m n =+    Map.size (toMap m) == Map.size (toMap n)+      && liftEq (liftEq2 eqk eqv) (toList m) (toList n)++instance Ord k => Ord1 (Multimap k) where+  liftCompare = liftCompare2 compare++instance Ord2 Multimap where+  liftCompare2 cmpk cmpv m n =+      liftCompare (liftCompare2 cmpk cmpv) (toList m) (toList n)++instance (Show k, Show a) => Show (Multimap k a) where+  showsPrec d m = showParen (d > 10) $+    showString "fromList " . shows (toList m)++instance Show k => Show1 (Multimap k) where+  liftShowsPrec = liftShowsPrec2 showsPrec showList++instance Show2 Multimap where+  liftShowsPrec2 spk slk spv slv d m =+      showsUnaryWith (liftShowsPrec sp sl) "fromList" d (toList m)+    where+      sp = liftShowsPrec2 spk slk spv slv+      sl = liftShowList2 spk slk spv slv++instance (Ord k, Read k, Read e) => Read (Multimap k e) where+  readsPrec p = readParen (p > 10) $ \ r -> do+    ("fromList",s) <- lex r+    (xs,t) <- reads s+    pure (fromList xs,t)++instance (Ord k, Read k) => Read1 (Multimap k) where+  liftReadsPrec rp rl = readsData $+      readsUnaryWith (liftReadsPrec rp' rl') "fromList" fromList+    where+      rp' = liftReadsPrec rp rl+      rl' = liftReadList rp rl++instance Functor (Multimap k) where+  fmap = map++instance Foldable.Foldable (Multimap k) where+  foldMap = foldMapWithKey . const+  {-# INLINE foldMap #-}++instance Traversable (Multimap k) where+  traverse = traverseWithKey . const+  {-# INLINE traverse #-}++instance (Ord k) => Semigroup (Multimap k a) where+  (<>) = union++instance (Ord k) => Monoid (Multimap k a) where+  mempty = empty+  mappend = (<>)++------------------------------------------------------------------------------++-- | /O(1)/. The empty multimap.+--+-- > size empty === 0+empty :: Multimap k a+empty = Multimap (Map.empty, 0)++-- | /O(1)/. A multimap with a single element.+--+-- > singleton 1 'a' === fromList [(1, 'a')]+-- > size (singleton 1 'a') === 1+singleton :: k -> a -> Multimap k a+singleton k a = Multimap (Map.singleton k (pure a), 1)++-- | /O(n*log n)/ where /n/ is the length of the input list.+--  Build a multimap from a list of key\/value pairs.+--+-- > fromList ([] :: [(Int, Char)]) === empty+fromList :: Ord k => [(k, a)] -> Multimap k a+fromList = Foldable.foldr (uncurry insert) empty++-- | /O(1)/.+fromMap :: Map k (NonEmpty a) -> Multimap k a+fromMap m = Multimap (m, sum (fmap length m))++-- | /O(k)/. A key is retained only if it is associated with a+-- non-empty list of values.+--+-- > fromMap' (Map.fromList [(1, "ab"), (2, ""), (3, "c")]) === fromList [(1, 'a'), (1, 'b'), (3, 'c')]+fromMap' :: Map k [a] -> Multimap k a+fromMap' m = Multimap (Map.mapMaybe nonEmpty m, sum (fmap length m))++------------------------------------------------------------------------------++-- | /O(log k)/. If the key exists in the multimap, the new value will be+-- prepended to the list of values for the key.+--+-- > insert 1 'a' empty === singleton 1 'a'+-- > insert 1 'a' (fromList [(2, 'b'), (2, 'c')]) === fromList [(1, 'a'), (2, 'b'), (2, 'c')]+-- > insert 1 'a' (fromList [(1, 'b'), (2, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]+insert :: Ord k => k -> a -> Multimap k a -> Multimap k a+insert k a (Multimap (m, _)) = fromMap (Map.alter f k m)+  where+    f (Just as) = Just (a <| as)+    f Nothing = Just (pure a)++-- | /O(log k)/. Delete a key and all its values from the map.+--+-- > delete 1 (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === singleton 2 'c'+delete :: Ord k => k -> Multimap k a -> Multimap k a+delete = update' (const [])++-- | /O(m*log k)/. Remove the first+-- occurrence of the value associated with the key, if exists.+--+-- > deleteWithValue 1 'c' (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]+-- > deleteWithValue 1 'c' (fromList [(1, 'a'), (1, 'b'), (2, 'c'), (1, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]+-- > deleteWithValue 1 'c' (fromList [(2, 'c'), (1, 'c')]) === singleton 2 'c'+deleteWithValue :: (Ord k, Eq a) => k -> a -> Multimap k a -> Multimap k a+deleteWithValue k a = update' (List.delete a . Nel.toList) k++-- | /O(log k)/. Remove the first+-- value associated with the key. If the key is associated with a single value,+-- the key will be removed from the multimap.+--+-- > deleteOne 1 (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === fromList [(1, 'b'), (2, 'c')]+-- > deleteOne 1 (fromList [(2, 'c'), (1, 'c')]) === singleton 2 'c'+deleteOne :: Ord k => k -> Multimap k a -> Multimap k a+deleteOne = update' Nel.tail++-- | /O(m*log k)/, assuming the function @a -> a@ takes /O(1)/.+-- Update values at a specific key, if exists.+--+-- > adjust ("new " ++) 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(1,"new b"),(2,"c")]+adjust :: Ord k => (a -> a) -> k -> Multimap k a -> Multimap k a+adjust = adjustWithKey . const++-- | /O(m*log k)/, assuming the function @k -> a -> a@ takes /O(1)/.+-- Update values at a specific key, if exists.+--+-- > adjustWithKey (\k x -> show k ++ ":new " ++ x) 1 (fromList [(1,"a"),(1,"b"),(2,"c")])+-- >   === fromList [(1,"1:new a"),(1,"1:new b"),(2,"c")]+adjustWithKey :: Ord k => (k -> a -> a) -> k -> Multimap k a -> Multimap k a+adjustWithKey f k (Multimap (m, sz)) = Multimap (m', sz)+  where+    m' = Map.adjustWithKey (fmap . f) k m++-- | /O(m*log k)/, assuming the function @a -> 'Maybe' a@ takes /O(1)/.+-- The expression (@'update' f k map@) updates the values at key @k@, if+-- exists. If @f@ returns 'Nothing' for a value, the value is deleted.+--+-- > let f x = if x == "a" then Just "new a" else Nothing in do+-- >   update f 1 (fromList [(1,"a"),(1, "b"),(2,"c")]) === fromList [(1,"new a"),(2, "c")]+-- >   update f 1 (fromList [(1,"b"),(1, "b"),(2,"c")]) === singleton 2 "c"+update :: Ord k => (a -> Maybe a) -> k -> Multimap k a -> Multimap k a+update = updateWithKey . const++-- | /O(log k)/, assuming the function @'NonEmpty' a -> [a]@ takes /O(1)/.+-- The expression (@'update' f k map@) updates the values at key @k@, if+-- exists. If @f@ returns 'Nothing', the key is deleted.+--+-- > update' NonEmpty.tail 1 (fromList [(1, "a"), (1, "b"), (2, "c")]) === fromList [(1, "b"), (2, "c")]+-- > update' NonEmpty.tail 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"+update' :: Ord k => (NonEmpty a -> [a]) -> k -> Multimap k a -> Multimap k a+update' = updateWithKey' . const++-- | /O(m*log k)/, assuming the function @k -> a -> 'Maybe' a@ takes /O(1)/.+-- The expression (@'updateWithKey' f k map@) updates the values at key @k@, if+-- exists. If @f@ returns 'Nothing' for a value, the value is deleted.+--+-- > let f k x = if x == "a" then Just (show k ++ ":new a") else Nothing in do+-- >   updateWithKey f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"1:new a"),(2,"c")]+-- >   updateWithKey f 1 (fromList [(1,"b"),(1,"b"),(2,"c")]) === singleton 2 "c"+updateWithKey :: Ord k => (k -> a -> Maybe a) -> k -> Multimap k a -> Multimap k a+updateWithKey f = alterWithKey (Maybe.mapMaybe . f)++-- | /O(log k)/, assuming the function @k -> 'NonEmpty' a -> [a]@ takes /O(1)/.+-- The expression (@'update' f k map@) updates the values at key @k@, if+-- exists. If @f@ returns 'Nothing', the key is deleted.+--+-- > let f k xs = if NonEmpty.length xs == 1 then (show k : NonEmpty.toList xs) else [] in do+-- >   updateWithKey' f 1 (fromList [(1, "a"), (1, "b"), (2, "c")]) === singleton 2 "c"+-- >   updateWithKey' f 1 (fromList [(1, "a"), (2, "b"), (2, "c")]) === fromList [(1, "1"), (1, "a"), (2, "b"), (2, "c")]+updateWithKey' :: Ord k => (k -> NonEmpty a -> [a]) -> k -> Multimap k a -> Multimap k a+updateWithKey' f = alterWithKey g+  where+    g _ [] = []+    g k (a:as) = f k (a :| as)++-- | /O(log k)/, assuming the function @[a] -> [a]@ takes /O(1)/.+-- The expression (@'alter' f k map@) alters the values at k, if exists.+--+-- > let (f, g) = (const [], ('c':)) in do+-- >   alter f 1 (fromList [(1, 'a'), (2, 'b')]) === singleton 2 'b'+-- >   alter f 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b')]+-- >   alter g 1 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'c'), (1, 'a'), (2, 'b')]+-- >   alter g 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b'), (3, 'c')]+alter :: Ord k => ([a] -> [a]) -> k -> Multimap k a -> Multimap k a+alter = alterWithKey . const++-- | /O(log k)/, assuming the function @k -> [a] -> [a]@ takes /O(1)/.+-- The expression (@'alterWithKey' f k map@) alters the values at k, if exists.+--+-- > let (f, g) = (const (const []), (:) . show) in do+-- >   alterWithKey f 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"+-- >   alterWithKey f 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b")]+-- >   alterWithKey g 1 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "1"), (1, "a"), (2, "b")]+-- >   alterWithKey g 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b"), (3, "3")]+alterWithKey :: Ord k => (k -> [a] -> [a]) -> k -> Multimap k a -> Multimap k a+alterWithKey f k mm@(Multimap (m, _)) = case nonEmpty (f k (mm ! k)) of+    Just as' -> fromMap (Map.insert k as' m)+    Nothing -> fromMap (Map.delete k m)++------------------------------------------------------------------------------++-- | /O(log k)/. Lookup the values at a key in the map. It returns an empty+-- list if the key is not in the map.+lookup :: Ord k => k -> Multimap k a -> [a]+lookup k (Multimap (m, _)) = maybe [] Nel.toList (Map.lookup k m)++-- | /O(log k)/. Lookup the values at a key in the map. It returns an empty+-- list if the key is not in the map.+--+-- > fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 3 === "ac"+-- > fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 2 === []+(!) :: Ord k => Multimap k a -> k -> [a]+(!) = flip lookup++-- | /O(log k)/. Is the key a member of the map?+--+-- A key is a member of the map if and only if there is at least one value+-- associated with it.+--+-- > member 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === True+-- > member 1 (deleteOne 1 (fromList [(2, 'c'), (1, 'c')])) === False+member :: Ord k => k -> Multimap k a -> Bool+member k (Multimap (m, _)) = Map.member k m++-- | /O(log k)/. Is the key not a member of the map?+--+-- A key is a member of the map if and only if there is at least one value+-- associated with it.+--+-- > notMember 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === False+-- > notMember 1 (deleteOne 1 (fromList [(2, 'c'), (1, 'c')])) === True+notMember :: Ord k => k -> Multimap k a -> Bool+notMember k = not . member k++-- | /O(1)/. Is the multimap empty?+--+-- > Data.Multimap.null empty === True+-- > Data.Multimap.null (singleton 1 'a') === False+null :: Multimap k a -> Bool+null (Multimap (m, _)) = Map.null m++-- | /O(1)/. Is the multimap non-empty?+--+-- > notNull empty === False+-- > notNull (singleton 1 'a') === True+notNull :: Multimap k a -> Bool+notNull = not . null++-- | The total number of values for all keys.+--+-- @size@ is evaluated lazily. Forcing the size for the first time takes up to+-- /O(n)/ and subsequent forces take /O(1)/.+--+-- > size empty === 0+-- > size (singleton 1 'a') === 1+-- > size (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === 3+size :: Multimap k a -> Int+size (Multimap (_, sz)) = sz++------------------------------------------------------------------------------++-- | Union two multimaps, concatenating values for duplicate keys.+--+-- > union (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b')])+-- >   === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c'),(2,'b')]+union :: Ord k => Multimap k a -> Multimap k a -> Multimap k a+union (Multimap (m1, _)) (Multimap (m2, _)) =+  fromMap (Map.unionWith (<>) m1 m2)++-- | Union a number of multimaps, concatenating values for duplicate keys.+--+-- > unions [fromList [(1,'a'),(2,'b'),(2,'c')], fromList [(1,'d'),(2,'b')]]+-- >   === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c'),(2,'b')]+unions :: (Foldable f, Ord k) => f (Multimap k a) -> Multimap k a+unions = Foldable.foldr union empty++-- | Difference of two multimaps.+--+-- If a key exists in the first multimap but not the second, it remains+-- unchanged in the result. If a key exists in both multimaps, a list+-- difference is performed on their values, i.e., the first occurrence+-- of each value in the second multimap is removed from the+-- first multimap.+--+-- > difference (fromList [(1,'a'),(2,'b'),(2,'c'),(2,'b')]) (fromList [(1,'d'),(2,'b'),(2,'a')])+-- >   === fromList [(1,'a'), (2,'c'), (2,'b')]+difference :: (Ord k, Eq a) => Multimap k a -> Multimap k a -> Multimap k a+difference (Multimap (m1, _)) (Multimap (m2, _)) = fromMap $+  Map.differenceWith (\xs ys -> nonEmpty (Nel.toList xs List.\\ Nel.toList ys)) m1 m2++------------------------------------------------------------------------------++-- | /O(n)/, assuming the function @a -> b@ takes /O(1)/.+-- Map a function over all values in the map.+--+-- > Data.Multimap.map (++ "x") (fromList [(1,"a"),(1,"a"),(2,"b")]) === fromList [(1,"ax"),(1,"ax"),(2,"bx")]+map :: (a -> b) -> Multimap k a -> Multimap k b+map = mapWithKey . const++-- | /O(n)/, assuming the function @k -> a -> b@ takes /O(1)/.+-- Map a function over all key\/value pairs in the map.+--+-- > mapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1,"a"),(1,"a"),(2,"b")]) === fromList [(1,"1:a"),(1,"1:a"),(2,"2:b")]+mapWithKey :: (k -> a -> b) -> Multimap k a -> Multimap k b+mapWithKey f (Multimap (m, sz)) = Multimap (Map.mapWithKey (fmap . f) m, sz)++-- | Traverse key\/value pairs and collect the results.+--+-- > let f k a = if odd k then Just (succ a) else Nothing in do+-- >   traverseWithKey f (fromList [(1, 'a'), (1, 'b'), (3, 'b'), (3, 'c')]) === Just (fromList [(1, 'b'), (1, 'c'), (3, 'c'), (3, 'd')])+-- >   traverseWithKey f (fromList [(1, 'a'), (1, 'b'), (2, 'b')]) === Nothing+traverseWithKey :: Applicative t => (k -> a -> t b) -> Multimap k a -> t (Multimap k b)+traverseWithKey f (Multimap (m, _)) =+  fromMap <$> Map.traverseWithKey (traverse . f) m++-- | Traverse key\/value pairs and collect the 'Just' results.+traverseMaybeWithKey :: Applicative t => (k -> a -> t (Maybe b)) -> Multimap k a -> t (Multimap k b)+traverseMaybeWithKey f (Multimap (m, _)) =+    fromMap <$> Map.traverseMaybeWithKey f' m+  where+    f' k = fmap (nonEmpty . Maybe.catMaybes) . traverse (f k) . Nel.toList++------------------------------------------------------------------------------++-- | /O(n)/. Fold the values in the map using the given right-associative+-- binary operator.+--+-- > Data.Multimap.foldr ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+foldr :: (a -> b -> b) -> b -> Multimap k a -> b+foldr = foldrWithKey . const++-- | /O(n)/. Fold the values in the map using the given left-associative+-- binary operator.+--+-- > Data.Multimap.foldl (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+foldl :: (a -> b -> a) -> a -> Multimap k b -> a+foldl = foldlWithKey . (const .)++-- | /O(n)/. Fold the key\/value pairs in the map using the given+-- right-associative binary operator.+--+-- > foldrWithKey (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+foldrWithKey :: (k -> a -> b -> b) -> b -> Multimap k a -> b+foldrWithKey f b (Multimap (m, _)) = Map.foldrWithKey f' b m+  where+    f' = flip . Foldable.foldr . f++-- | /O(n)/. Fold the key\/value pairs in the map using the given+-- left-associative binary operator.+--+-- > foldlWithKey (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+foldlWithKey :: (a -> k -> b -> a) -> a -> Multimap k b -> a+foldlWithKey f a (Multimap (m, _)) = Map.foldlWithKey f' a m+  where+    f' = flip (Foldable.foldl . flip f)++-- | /O(n)/. A strict version of 'foldr'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > Data.Multimap.foldr' ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+foldr' :: (a -> b -> b) -> b -> Multimap k a -> b+foldr' = foldrWithKey' . const++-- | /O(n)/. A strict version of 'foldl'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > Data.Multimap.foldl' (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+foldl' :: (a -> b -> a) -> a -> Multimap k b -> a+foldl' = foldlWithKey' . (const .)++-- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > foldrWithKey' (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+foldrWithKey' :: (k -> a -> b -> b) -> b -> Multimap k a -> b+foldrWithKey' f b (Multimap (m, _)) = Map.foldrWithKey' f' b m+  where+    f' = flip . Foldable.foldr . f++-- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > foldlWithKey' (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+foldlWithKey' :: (a -> k -> b -> a) -> a -> Multimap k b -> a+foldlWithKey' f a (Multimap (m, _)) = Map.foldlWithKey' f' a m+  where+    f' = flip (Foldable.foldl' . flip f)++-- | /O(n)/. Fold the key\/value pairs in the map using the given monoid.+--+-- > foldMapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1, "a"), (1, "a"), (2, "b")]) === "1:a1:a2:b"+foldMapWithKey :: Monoid m => (k -> a -> m) -> Multimap k a -> m+foldMapWithKey f (Multimap (m, _)) = Map.foldMapWithKey f' m+  where+    f' = Foldable.foldMap . f++------------------------------------------------------------------------------++-- | /O(n)/. Return all elements of the multimap in ascending order of+-- their keys.+--+-- > elems (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === "bbac"+-- > elems (empty :: Multimap Int Char) === []+elems :: Multimap k a -> [a]+elems (Multimap (m, _)) = Map.elems m >>= Nel.toList++-- | /O(k)/. Return all keys of the multimap in ascending order.+--+-- > keys (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === [1,2,3]+-- > keys (empty :: Multimap Int Char) === []+keys :: Multimap k a -> [k]+keys (Multimap (m, _)) = Map.keys m++-- | /O(k)/. The set of all keys of the multimap.+--+-- > keysSet (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === Set.fromList [1,2,3]+-- > keysSet (empty :: Multimap Int Char) === Set.empty+keysSet :: Multimap k a -> Set k+keysSet (Multimap (m, _)) = Map.keysSet m++-- | An alias for 'toAscList'.+--+-- > assocs (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]+assocs :: Multimap k a -> [(k, a)]+assocs = toAscList++-- | Convert the multimap into a list of key/value pairs.+--+-- > toList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]+toList :: Multimap k a -> [(k, a)]+toList = toAscList++-- | Convert the multimap into a list of key/value pairs in ascending+-- order of keys.+--+-- > toAscList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]+toAscList :: Multimap k a -> [(k, a)]+toAscList (Multimap (m, _)) =+  Map.toAscList m >>= uncurry (\k -> fmap (k,) . Nel.toList)++-- | Convert the multimap into a list of key/value pairs in descending+-- order of keys.+--+-- > toDescList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(3,'c'),(2,'a'),(1,'b'),(1,'a')]+toDescList :: Multimap k a -> [(k, a)]+toDescList (Multimap (m, _)) =+  Map.toDescList m >>= uncurry (\k -> fmap (k,) . Nel.toList)++-- | Convert the multimap into a list of key/value pairs, in a+-- breadth-first manner, in ascending order of keys.+--+-- > toAscListBF (fromList [("Foo",1),("Foo",2),("Foo",3),("Bar",4),("Bar",5),("Baz",6)])+-- >   === [("Bar",4),("Baz",6),("Foo",1),("Bar",5),("Foo",2),("Foo",3)]+toAscListBF :: Multimap k a -> [(k, a)]+toAscListBF (Multimap (m, _)) =+  join+  . List.transpose+  . fmap (uncurry (\k -> fmap (k,) . Nel.toList))+  $ Map.toAscList m++-- | Convert the multimap into a list of key/value pairs, in a+-- breadth-first manner, in descending order of keys.+--+-- > toDescListBF (fromList [("Foo",1),("Foo",2),("Foo",3),("Bar",4),("Bar",5),("Baz",6)])+-- >   === [("Foo",1),("Baz",6),("Bar",4),("Foo",2),("Bar",5),("Foo",3)]+toDescListBF :: Multimap k a -> [(k, a)]+toDescListBF (Multimap (m, _)) =+  join+  . List.transpose+  . fmap (uncurry (\k -> fmap (k,) . Nel.toList))+  $ Map.toDescList m++-- | /O(1)/. Convert the multimap into a regular map.+toMap :: Multimap k a -> Map k (NonEmpty a)+toMap (Multimap (m, _)) = m++------------------------------------------------------------------------------++-- | /O(n)/, assuming the predicate function takes /O(1)/.+-- Retain all values that satisfy the predicate.+--+-- > Data.Multimap.filter (> 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 1 'b'+-- > Data.Multimap.filter (< 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === empty+filter :: (a -> Bool) -> Multimap k a -> Multimap k a+filter = filterWithKey . const++-- | /O(k)/, assuming the predicate function takes /O(1)/.+-- Retain all keys that satisfy the predicate.+--+-- > filterKey even (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 2 'a'+filterKey :: (k -> Bool) -> Multimap k a -> Multimap k a+filterKey p (Multimap (m, _)) = fromMap m'+  where+    m' = Map.filterWithKey (const . p) m++-- | /O(n)/, assuming the predicate function takes /O(1)/.+-- Retain all key\/value pairs that satisfy the predicate.+--+-- > filterWithKey (\k a -> even k && a > 'a') (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'b')]) === singleton 2 'b'+filterWithKey :: (k -> a -> Bool) -> Multimap k a -> Multimap k a+filterWithKey p (Multimap (m, _)) = fromMap m'+  where+    m' = Map.mapMaybeWithKey (\k -> nonEmpty . Nel.filter (p k)) m++-- | Generalized 'filter'.+--+-- > let f a | a > 'b' = Just True+-- >         | a < 'b' = Just False+-- >         | a == 'b' = Nothing+-- >  in do+-- >    filterM f (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'c')]) === Nothing+-- >    filterM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Just (fromList [(1,'c'),(2,'c')])+filterM :: (Ord k, Applicative t) => (a -> t Bool) -> Multimap k a -> t (Multimap k a)+filterM = filterWithKeyM . const++-- | Generalized 'filterWithKey'.+--+-- > let f k a | even k && a > 'b' = Just True+-- >           | odd k && a < 'b' = Just False+-- >           | otherwise = Nothing+-- >  in do+-- >    filterWithKeyM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Nothing+-- >    filterWithKeyM f (fromList [(1,'a'),(1,'a'),(2,'c'),(2,'c')]) === Just (fromList [(2,'c'),(2,'c')])+filterWithKeyM :: (Ord k, Applicative t) => (k -> a -> t Bool) -> Multimap k a -> t (Multimap k a)+filterWithKeyM f = fmap fromList . List.filterM (uncurry f) . toList++-- | /O(n)/, assuming the function @a -> 'Maybe' b@ takes /O(1)/.+-- Map values and collect the 'Just' results.+--+-- > mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])+-- >   === fromList [(1,"new a"),(2,"new a")]+mapMaybe :: (a -> Maybe b) -> Multimap k a -> Multimap k b+mapMaybe = mapMaybeWithKey . const++-- | /O(n)/, assuming the function @k -> a -> 'Maybe' b@ takes /O(1)/.+-- Map key\/value pairs and collect the 'Just' results.+--+-- > mapMaybeWithKey (\k a -> if k > 1 && a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])+-- >   === singleton 2 "new a"+mapMaybeWithKey :: (k -> a -> Maybe b) -> Multimap k a -> Multimap k b+mapMaybeWithKey f (Multimap (m, _)) = fromMap $+  Map.mapMaybeWithKey (\k -> nonEmpty . Maybe.mapMaybe (f k) . Nel.toList) m++-- | /O(n)/, assuming the function @a -> 'Either' b c@ takes /O(1)/.+-- Map values and separate the 'Left' and 'Right' results.+--+-- > mapEither (\a -> if a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])+-- >   === (fromList [(1,'a'),(2,'a')],fromList [(1,'c'),(2,'c')])+mapEither :: (a -> Either b c) -> Multimap k a -> (Multimap k b, Multimap k c)+mapEither = mapEitherWithKey . const++-- | /O(n)/, assuming the function @k -> a -> 'Either' b c@ takes /O(1)/.+-- Map key\/value pairs and separate the 'Left' and 'Right' results.+--+-- > mapEitherWithKey (\k a -> if even k && a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])+-- >   === (fromList [(2,'a')],fromList [(1,'a'),(1,'c'),(2,'c')])+mapEitherWithKey :: (k -> a -> Either b c) -> Multimap k a -> (Multimap k b, Multimap k c)+mapEitherWithKey f (Multimap (m, _)) =+    (fromMap' . Map.mapWithKey (const fst) &&& fromMap' . Map.mapWithKey (const snd))+      $ Map.mapWithKey g m+  where+    g k as = Either.partitionEithers $ fmap (f k) (Nel.toList as)++------------------------------------------------------------------------------++-- | /O(log n)/. Return the smallest key and the associated values. Returns 'Nothing'+-- if the map is empty.+--+-- > lookupMin (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (1, NonEmpty.fromList "ac")+-- > lookupMin (empty :: Multimap Int Char) === Nothing+lookupMin :: Multimap k a -> Maybe (k, NonEmpty a)+lookupMin (Multimap (m, _)) = Map.lookupMin m++-- | /O(log n)/. Return the largest key and the associated values. Returns 'Nothing'+-- if the map is empty.+--+-- > lookupMax (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (2, NonEmpty.fromList "c")+-- > lookupMax (empty :: Multimap Int Char) === Nothing+lookupMax :: Multimap k a -> Maybe (k, NonEmpty a)+lookupMax (Multimap (m, _)) = Map.lookupMax m++-- | /O(log n)/. Return the largest key smaller than the given one, and the associated+-- values, if exist.+--+-- > lookupLT 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+-- > lookupLT 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")+lookupLT :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)+lookupLT k (Multimap (m, _)) = Map.lookupLT k m++-- | /O(log n)/. Return the smallest key larger than the given one, and the associated+-- values, if exist.+--+-- > lookupGT 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+-- > lookupGT 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")+lookupGT :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)+lookupGT k (Multimap (m, _)) = Map.lookupGT k m++-- | /O(log n)/. Return the largest key smaller than or equal to the given one, and the associated+-- values, if exist.+--+-- > lookupLE 0 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+-- > lookupLE 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (1, NonEmpty.fromList "a")+-- > lookupLE 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")+lookupLE :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)+lookupLE k (Multimap (m, _)) = Map.lookupLE k m++-- | /O(log n)/. Return the smallest key larger than or equal to the given one, and the associated+-- values, if exist.+--+-- > lookupGE 6 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+-- > lookupGE 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (5, NonEmpty.fromList "c")+-- > lookupGE 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")+lookupGE :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)+lookupGE k (Multimap (m, _)) = Map.lookupGE k m
src/Data/Multimap/Set.hs view
@@ -1,7 +1,3 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeFamilies #-}- ----------------------------------------------------------------------------- -- | -- Module      :  Data.Multimap.Set@@ -122,6 +118,11 @@   -- ** Maps   , toMap +  -- ** Multimaps+  , fromMultimap+  , toMultimapAsc+  , toMultimapDesc+   -- * Filter   , filter   , filterWithKey@@ -143,622 +144,13 @@   , lookupGE   ) where +import Data.Multimap.Conversions+import Data.Multimap.Internal (Multimap)+import Data.Multimap.Set.Internal import Prelude hiding (filter, foldl, foldr, lookup, map, null) -import           Control.Arrow ((&&&))-import qualified Control.Monad as List (filterM)-import           Data.Data (Data)-import qualified Data.Foldable as Foldable-import           Data.Functor.Classes-import           Data.Map.Lazy (Map)-import qualified Data.Map.Lazy as Map-import qualified Data.Maybe as Maybe-import           Data.Set (Set)-import qualified Data.Set as Set--infixl 9 !--type Size = Int--newtype SetMultimap k a = SetMultimap (Map k (Set a), Size)-  deriving (Eq, Ord, Data)--instance Eq k => Eq1 (SetMultimap k) where-  liftEq = liftEq2 (==)--instance Eq2 SetMultimap where-  liftEq2 eqk eqv m n =-    Map.size (toMap m) == Map.size (toMap n)-      && liftEq (liftEq2 eqk eqv) (toList m) (toList n)--instance Ord k => Ord1 (SetMultimap k) where-  liftCompare = liftCompare2 compare--instance Ord2 SetMultimap where-  liftCompare2 cmpk cmpv m n =-      liftCompare (liftCompare2 cmpk cmpv) (toList m) (toList n)--instance (Show k, Show a) => Show (SetMultimap k a) where-  showsPrec d m = showParen (d > 10) $-    showString "fromList " . shows (toList m)--instance Show k => Show1 (SetMultimap k) where-  liftShowsPrec = liftShowsPrec2 showsPrec showList--instance Show2 SetMultimap where-  liftShowsPrec2 spk slk spv slv d m =-      showsUnaryWith (liftShowsPrec sp sl) "fromList" d (toList m)-    where-      sp = liftShowsPrec2 spk slk spv slv-      sl = liftShowList2 spk slk spv slv--instance (Ord k, Ord a, Read k, Read a) => Read (SetMultimap k a) where-  readsPrec p = readParen (p > 10) $ \ r -> do-    ("fromList",s) <- lex r-    (xs,t) <- reads s-    pure (fromList xs,t)--instance Foldable.Foldable (SetMultimap k) where-  foldMap = foldMapWithKey . const-  {-# INLINE foldMap #-}--instance (Ord k, Ord a) => Semigroup (SetMultimap k a) where-  (<>) = union--instance (Ord k, Ord a) => Monoid (SetMultimap k a) where-  mempty = empty-  mappend = (<>)------------------------------------------------------------------------------------ | /O(1)/. The empty multimap.------ > size empty === 0-empty :: SetMultimap k a-empty = SetMultimap (Map.empty, 0)---- | /O(1)/. A multimap with a single element.------ > singleton 1 'a' === fromList [(1, 'a')]--- > size (singleton 1 'a') === 1-singleton :: k -> a -> SetMultimap k a-singleton k a = SetMultimap (Map.singleton k (Set.singleton a), 1)---- | /O(n*log n)/ where /n/ is the length of the input list.---  Build a multimap from a list of key\/value pairs.------ > fromList ([] :: [(Int, Char)]) === empty--- > fromList [(1, 'b'), (2, 'a'), (1, 'b')] === fromList [(1, 'b'), (2, 'a')]-fromList :: (Ord k, Ord a) => [(k, a)] -> SetMultimap k a-fromList = Foldable.foldr (uncurry insert) empty---- | /O(k)/. A key is retained only if it is associated with a--- non-empty set of values.-fromMap :: Map k (Set a) -> SetMultimap k a-fromMap m = SetMultimap (m', sum (fmap Set.size m'))-  where-    m' = Map.filter (not . Set.null) m------------------------------------------------------------------------------------ | /O(log m * log k)/. If the key exists in the multimap, the new value will--- be inserted into the set of values for the key. It is a no-op if the value--- already exists in the set.------ > insert 1 'a' empty === singleton 1 'a'--- > insert 1 'a' (fromList [(1, 'b'), (2, 'a')]) === fromList [(1, 'a'), (1, 'b'), (2, 'a')]--- > insert 1 'a' (fromList [(1, 'a'), (2, 'c')]) === fromList [(1, 'a'), (2, 'c')]-insert :: (Ord k, Ord a) => k -> a -> SetMultimap k a -> SetMultimap k a-insert k a (SetMultimap (m, _)) = fromMap' k (Map.alter f k m)-  where-    f (Just as) = Just (Set.insert a as)-    f Nothing = Just (Set.singleton a)---- | /O(log k)/. Delete a key and all its values from the map.------ > delete 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === singleton 2 'c'-delete :: Ord k => k -> SetMultimap k a -> SetMultimap k a-delete = alter (const Set.empty)---- | /O(log m * log k)/. Remove the first--- occurrence of the value associated with the key, if exists.------ > deleteWithValue 1 'c' (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]--- > deleteWithValue 1 'c' (fromList [(2,'c'),(1,'c')]) === singleton 2 'c'-deleteWithValue :: (Ord k, Ord a) => k -> a -> SetMultimap k a -> SetMultimap k a-deleteWithValue k a = alter (Set.delete a) k---- | /O(log m * log k)/. Remove the maximal value--- associated with the key, if exists.------ > deleteMax 3 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]--- > deleteMax 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(2,'c')]-deleteMax :: Ord k => k -> SetMultimap k a -> SetMultimap k a-deleteMax = alter Set.deleteMax---- | /O(log m * log k)/. Remove the minimal value--- associated with the key, if exists.------ > deleteMin 3 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]--- > deleteMin 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'b'),(2,'c')]-deleteMin :: Ord k => k -> SetMultimap k a -> SetMultimap k a-deleteMin = alter Set.deleteMin---- | /O(m * log m * log k)/, assuming the function @a -> a@ takes /O(1)/.--- Update values at a specific key, if exists.------ Since values are sets, the result may be smaller than the original multimap.------ > adjust ("new " ++) 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(1,"new b"),(2,"c")]--- > adjust (const "z") 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"z"),(2,"c")]-adjust :: (Ord k, Ord a) => (a -> a) -> k -> SetMultimap k a -> SetMultimap k a-adjust = adjustWithKey. const---- | /O(m * log m * log k)/, assuming the function @k -> a -> a@ takes /O(1)/.--- Update values at a specific key, if exists.------ Since values are sets, the result may be smaller than the original multimap.------ > adjustWithKey (\k x -> show k ++ ":new " ++ x) 1 (fromList [(1,"a"),(1,"b"),(2,"c")])--- >   === fromList [(1,"1:new a"),(1,"1:new b"),(2,"c")]-adjustWithKey :: (Ord k, Ord a) => (k -> a -> a) -> k -> SetMultimap k a -> SetMultimap k a-adjustWithKey f = alterWithKey (Set.map . f)---- | /O(m * log m * log k)/, assuming the function @a -> 'Maybe' a@--- takes /O(1)/. The expression (@'update' f k map@) updates the--- values at key @k@, if exists. If @f@ returns 'Nothing' for a value, the--- value is deleted.------ > let f x = if x == "a" then Just "new a" else Nothing in do--- >   update f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(2, "c")]--- >   update f 1 (fromList [(1,"b"),(1,"c"),(2,"c")]) === singleton 2 "c"-update :: (Ord k, Ord a) => (a -> Maybe a) -> k -> SetMultimap k a -> SetMultimap k a-update = updateWithKey . const---- | /O(m * log m * log k)/, assuming the function @k -> a -> 'Maybe' a@--- takes /O(1)/. The expression (@'updateWithKey' f k map@) updates the--- values at key @k@, if exists. If @f@ returns 'Nothing' for a value, the--- value is deleted.------ > let f k x = if x == "a" then Just (show k ++ ":new a") else Nothing in do--- >   updateWithKey f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"1:new a"),(2,"c")]--- >   updateWithKey f 1 (fromList [(1,"b"),(1,"c"),(2,"c")]) === singleton 2 "c"-updateWithKey :: (Ord k, Ord a) => (k -> a -> Maybe a) -> k -> SetMultimap k a -> SetMultimap k a-updateWithKey f = alterWithKey g-  where-    g k = catMaybes . Set.map (f k)---- | /O(log k)/, assuming the function @'Set' a -> 'Set' a@ takes /O(1)/.--- The expression (@'alter' f k map@) alters the values at k, if exists.------ > let (f, g) = (const Set.empty, Set.insert 'c') in do--- >   alter f 1 (fromList [(1, 'a'), (2, 'b')]) === singleton 2 'b'--- >   alter f 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b')]--- >   alter g 1 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'c'), (1, 'a'), (2, 'b')]--- >   alter g 1 (fromList [(1, 'c'), (2, 'b')]) === fromList [(1, 'c'), (2, 'b')]--- >   alter g 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b'), (3, 'c')]-alter :: Ord k => (Set a -> Set a) -> k -> SetMultimap k a -> SetMultimap k a-alter = alterWithKey . const---- | /O(log k)/, assuming the function @k -> 'Set' a -> 'Set' a@ takes /O(1)/.--- The expression (@'alterWithKey' f k map@) alters the values at k, if exists.------ > let (f, g) = (const (const Set.empty), Set.insert . show) in do--- >   alterWithKey f 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"--- >   alterWithKey f 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b")]--- >   alterWithKey g 1 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "1"), (1, "a"), (2, "b")]--- >   alterWithKey g 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b"), (3, "3")]-alterWithKey :: Ord k => (k -> Set a -> Set a) -> k -> SetMultimap k a -> SetMultimap k a-alterWithKey f k mm@(SetMultimap (m, _))-    | Set.null as = fromMap (Map.delete k m)-    | otherwise = fromMap (Map.insert k as m)-  where-    as = f k (mm ! k)------------------------------------------------------------------------------------ | /O(log k)/. Lookup the values at a key in the map. It returns an empty--- set if the key is not in the map.-lookup :: Ord k => k -> SetMultimap k a -> Set a-lookup k (SetMultimap (m, _)) = Maybe.fromMaybe Set.empty (Map.lookup k m)---- | /O(log k)/. Lookup the values at a key in the map. It returns an empty--- set if the key is not in the map.------ > fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 3 === Set.fromList "ac"--- > fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 2 === Set.empty-(!) :: Ord k => SetMultimap k a -> k -> Set a-(!) = flip lookup---- | /O(log k)/. Is the key a member of the map?------ A key is a member of the map if and only if there is at least one value--- associated with it.------ > member 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === True--- > member 1 (deleteMax 1 (fromList [(2, 'c'), (1, 'c')])) === False-member :: Ord k => k -> SetMultimap k a -> Bool-member k (SetMultimap (m, _)) = Map.member k m---- | /O(log k)/. Is the key not a member of the map?------ A key is a member of the map if and only if there is at least one value--- associated with it.------ > notMember 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === False--- > notMember 1 (deleteMin 1 (fromList [(2, 'c'), (1, 'c')])) === True-notMember :: Ord k => k -> SetMultimap k a -> Bool-notMember k = not . member k---- | /O(1)/. Is the multimap empty?------ > Data.Multimap.Set.null empty === True--- > Data.Multimap.Set.null (singleton 1 'a') === False-null :: SetMultimap k a -> Bool-null (SetMultimap (m, _)) = Map.null m---- | /O(1)/. Is the multimap non-empty?------ > notNull empty === False--- > notNull (singleton 1 'a') === True-notNull :: SetMultimap k a -> Bool-notNull = not . null---- | The total number of values for all keys.------ @size@ is evaluated lazily. Forcing the size for the first time takes up to--- /O(k)/ and subsequent forces take /O(1)/.------ > size empty === 0--- > size (singleton 1 'a') === 1--- > size (fromList [(1, 'a'), (2, 'b'), (2, 'c'), (2, 'b')]) === 3-size :: SetMultimap k a -> Int-size (SetMultimap (_, sz)) = sz------------------------------------------------------------------------------------ | Union two multimaps, unioning values for duplicate keys.------ > union (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b')])--- >   === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c')]-union :: (Ord k, Ord a) => SetMultimap k a -> SetMultimap k a -> SetMultimap k a-union (SetMultimap (m1, _)) (SetMultimap (m2, _)) =-  fromMap (Map.unionWith Set.union m1 m2)---- | Union a number of multimaps, unioning values for duplicate keys.------ > unions [fromList [(1,'a'),(2,'b'),(2,'c')], fromList [(1,'d'),(2,'b')]]--- >   === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c')]-unions :: (Foldable f, Ord k, Ord a) => f (SetMultimap k a) -> SetMultimap k a-unions = Foldable.foldr union empty---- | Difference of two multimaps.------ If a key exists in the first multimap but not the second, it remains--- unchanged in the result. If a key exists in both multimaps, a set--- difference is performed on their values.------ > difference (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b'),(2,'a')])--- >   === fromList [(1,'a'),(2,'c')]-difference :: (Ord k, Ord a) => SetMultimap k a -> SetMultimap k a -> SetMultimap k a-difference (SetMultimap (m1, _)) (SetMultimap (m2, _)) = fromMap $-  Map.differenceWith (\xs ys -> Just (xs Set.\\ ys)) m1 m2------------------------------------------------------------------------------------ | /O(n * log m)/, assuming the function @a -> b@ takes /O(1)/.--- Map a function over all values in the map.------ Since values are sets, the result may be smaller than the original multimap.------ > Data.Multimap.Set.map (++ "x") (fromList [(1,"a"),(2,"b")]) === fromList [(1,"ax"),(2,"bx")]--- > Data.Multimap.Set.map (const "c") (fromList [(1,"a"),(1,"b"),(2,"b")]) === fromList [(1,"c"),(2,"c")]-map :: Ord b => (a -> b) -> SetMultimap k a -> SetMultimap k b-map = mapWithKey . const---- | /O(n * log m)/, assuming the function @k -> a -> b@ takes /O(1)/.--- Map a function over all values in the map.------ Since values are sets, the result may be smaller than the original multimap.------ > mapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1,"a"),(2,"b")]) === fromList [(1,"1:a"),(2,"2:b")]-mapWithKey :: Ord b => (k -> a -> b) -> SetMultimap k a -> SetMultimap k b-mapWithKey f (SetMultimap (m, _)) = fromMap $ Map.mapWithKey (Set.map . f) m---- | /O(n)/. Fold the values in the map using the given right-associative--- binary operator.------ > Data.Multimap.Set.foldr ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-foldr :: (a -> b -> b) -> b -> SetMultimap k a -> b-foldr = foldrWithKey . const---- | /O(n)/. Fold the values in the map using the given left-associative--- binary operator.------ > Data.Multimap.Set.foldl (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-foldl :: (a -> b -> a) -> a -> SetMultimap k b -> a-foldl = foldlWithKey . (const .)---- | /O(n)/. Fold the key\/value pairs in the map using the given--- right-associative binary operator.------ > foldrWithKey (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-foldrWithKey :: (k -> a -> b -> b) -> b -> SetMultimap k a -> b-foldrWithKey f b (SetMultimap (m, _)) = Map.foldrWithKey f' b m-  where-    f' = flip . Set.foldr . f---- | /O(n)/. Fold the key\/value pairs in the map using the given--- left-associative binary operator.------ > foldlWithKey (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-foldlWithKey :: (a -> k -> b -> a) -> a -> SetMultimap k b -> a-foldlWithKey f a (SetMultimap (m, _)) = Map.foldlWithKey f' a m-  where-    f' = flip (Set.foldl . flip f)---- | /O(n)/. A strict version of 'foldr'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > Data.Multimap.Set.foldr' ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-foldr' :: (a -> b -> b) -> b -> SetMultimap k a -> b-foldr' = foldrWithKey' . const---- | /O(n)/. A strict version of 'foldl'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > Data.Multimap.Set.foldl' (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-foldl' :: (a -> b -> a) -> a -> SetMultimap k b -> a-foldl' = foldlWithKey' . (const .)---- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > foldrWithKey' (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-foldrWithKey' :: (k -> a -> b -> b) -> b -> SetMultimap k a -> b-foldrWithKey' f b (SetMultimap (m, _)) = Map.foldrWithKey f' b m-  where-    f' = flip . Set.foldr' . f---- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > foldlWithKey' (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-foldlWithKey' :: (a -> k -> b -> a) -> a -> SetMultimap k b -> a-foldlWithKey' f a (SetMultimap (m, _)) = Map.foldlWithKey f' a m-  where-    f' = flip (Set.foldl' . flip f)---- | /O(n)/. Fold the key\/value pairs in the map using the given monoid.------ > foldMapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1, "a"), (1, "c"), (2, "b")]) === "1:a1:c2:b"-foldMapWithKey :: Monoid m => (k -> a -> m) -> SetMultimap k a -> m-foldMapWithKey f (SetMultimap (m, _)) = Map.foldMapWithKey f' m-  where-    f' = Foldable.foldMap . f------------------------------------------------------------------------------------ | /O(n)/. Return all elements of the multimap in ascending order of--- their keys. Elements of each key appear in ascending order.------ > elems (fromList [(2,'a'),(1,'b'),(3,'d'),(3,'c'),(1,'b')]) === "bacd"--- > elems (empty :: SetMultimap Int Char) === []-elems :: SetMultimap k a -> [a]-elems (SetMultimap (m, _)) = Map.elems m >>= Set.toList---- | /O(k)/. Return all keys of the multimap in ascending order.------ > keys (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'b')]) === [1,2,3]--- > keys (empty :: SetMultimap Int Char) === []-keys :: SetMultimap k a -> [k]-keys (SetMultimap (m, _)) = Map.keys m---- | /O(k)/. The set of all keys of the multimap.------ > keysSet (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'b')]) === Set.fromList [1,2,3]--- > keysSet (empty :: SetMultimap Int Char) === Set.empty-keysSet :: SetMultimap k a -> Set k-keysSet (SetMultimap (m, _)) = Map.keysSet m---- | An alias for 'toAscList'.-assocs :: SetMultimap k a -> [(k, a)]-assocs = toAscList---- | Convert the multimap into a list of key/value pairs.------ > toList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'a'),(1,'b'),(2,'a'),(3,'c')]-toList :: SetMultimap k a -> [(k, a)]-toList = toAscList---- | Convert the multimap into a list of key/value pairs in ascending--- order of keys. Elements of each key appear in ascending order.------ > toAscList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'a'),(1,'b'),(2,'a'),(3,'c')]-toAscList :: SetMultimap k a -> [(k, a)]-toAscList (SetMultimap (m, _)) =-  Map.toAscList m >>= uncurry (\k -> fmap (k,) . Set.toAscList)---- | Convert the multimap into a list of key/value pairs in descending--- order of keys. Elements of each key appear in descending order.------ > toDescList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(3,'c'),(2,'a'),(1,'b'),(1,'a')]-toDescList :: SetMultimap k a -> [(k, a)]-toDescList (SetMultimap (m, _)) =-  Map.toDescList m >>= uncurry (\k -> fmap (k,) . Set.toDescList)---- | /O(1)/. Convert the multimap into a regular map.-toMap :: SetMultimap k a -> Map k (Set a)-toMap (SetMultimap (m, _)) = m------------------------------------------------------------------------------------ | /O(n)/, assuming the predicate function takes /O(1)/.--- Retain all values that satisfy the predicate. A key is removed if--- none of its values satisfies the predicate.------ > Data.Multimap.Set.filter (> 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 1 'b'--- > Data.Multimap.Set.filter (< 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === empty-filter :: (a -> Bool) -> SetMultimap k a -> SetMultimap k a-filter = filterWithKey . const---- | /O(k)/, assuming the predicate function takes /O(1)/.--- Retain all keys that satisfy the predicate.-filterKey :: (k -> Bool) -> SetMultimap k a -> SetMultimap k a-filterKey p (SetMultimap (m, _)) = fromMap m'-  where-    m' = Map.filterWithKey (const . p) m---- | /O(n)/, assuming the predicate function takes /O(1)/.--- Retain all key\/value pairs that satisfy the predicate. A key is removed if--- none of its values satisfies the predicate.------ > filterWithKey (\k a -> even k && a > 'a') (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'b')]) === singleton 2 'b'-filterWithKey :: (k -> a -> Bool) -> SetMultimap k a -> SetMultimap k a-filterWithKey p (SetMultimap (m, _)) = fromMap m'-  where-    m' = Map.mapWithKey (Set.filter . p) m---- | Generalized 'filter'.------ > let f a | a > 'b' = Just True--- >         | a < 'b' = Just False--- >         | a == 'b' = Nothing--- >  in do--- >    filterM f (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'c')]) === Nothing--- >    filterM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Just (fromList [(1,'c'),(2,'c')])-filterM-  :: (Ord k, Ord a, Applicative t)-  => (a -> t Bool) -> SetMultimap k a -> t (SetMultimap k a)-filterM = filterWithKeyM . const---- | Generalized 'filterWithKey'.--- | Generalized 'filterWithKey'.------ > let f k a | even k && a > 'b' = Just True--- >           | odd k && a < 'b' = Just False--- >           | otherwise = Nothing--- >  in do--- >    filterWithKeyM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Nothing--- >    filterWithKeyM f (fromList [(1,'a'),(3,'a'),(2,'c'),(4,'c')]) === Just (fromList [(2,'c'),(4,'c')])-filterWithKeyM-  :: (Ord k, Ord a, Applicative t)-  => (k -> a -> t Bool) -> SetMultimap k a -> t (SetMultimap k a)-filterWithKeyM f = fmap fromList . List.filterM (uncurry f) . toList---- | /O(n * log m)/, assuming the function @a -> 'Maybe' b@ takes /O(1)/.--- Map values and collect the 'Just' results.------ > mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])--- >   === fromList [(1,"new a"),(2,"new a")]-mapMaybe :: Ord b => (a -> Maybe b) -> SetMultimap k a -> SetMultimap k b-mapMaybe = mapMaybeWithKey . const---- | /O(n * log m)/, assuming the function @k -> a -> 'Maybe' b@ takes /O(1)/.--- Map key\/value pairs and collect the 'Just' results.------ > mapMaybeWithKey (\k a -> if k > 1 && a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])--- >   === singleton 2 "new a"-mapMaybeWithKey :: Ord b => (k -> a -> Maybe b) -> SetMultimap k a -> SetMultimap k b-mapMaybeWithKey f (SetMultimap (m, _)) = fromMap $-  Map.mapWithKey (\k -> catMaybes . Set.map (f k)) m---- | /O(n * log m)/, assuming the function @a -> 'Either' b c@ takes /O(1)/.--- Map values and separate the 'Left' and 'Right' results.------ > mapEither (\a -> if a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])--- >   === (fromList [(1,'a'),(2,'a')],fromList [(1,'c'),(2,'c')])-mapEither-  :: (Ord b, Ord c)-  => (a -> Either b c) -> SetMultimap k a -> (SetMultimap k b, SetMultimap k c)-mapEither = mapEitherWithKey . const---- | /O(n * log m)/, assuming the function @k -> a -> 'Either' b c@ takes /O(1)/.--- Map key\/value pairs and separate the 'Left' and 'Right' results.------ > mapEitherWithKey (\k a -> if even k && a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])--- >   === (fromList [(2,'a')],fromList [(1,'a'),(1,'c'),(2,'c')])-mapEitherWithKey-  :: (Ord b, Ord c)-  => (k -> a -> Either b c) -> SetMultimap k a -> (SetMultimap k b, SetMultimap k c)-mapEitherWithKey f (SetMultimap (m, _)) =-  (fromMap . Map.mapWithKey (const fst) &&& fromMap . Map.mapWithKey (const snd))-      $ Map.mapWithKey g m-  where-    g k = partitionEithers . Set.map (f k)------------------------------------------------------------------------------------ | /O(log n)/. Return the smallest key and the associated values. Returns 'Nothing'--- if the map is empty.------ > lookupMin (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (1, Set.fromList "ac")--- > lookupMin (empty :: SetMultimap Int Char) === Nothing-lookupMin :: SetMultimap k a -> Maybe (k, Set a)-lookupMin (SetMultimap (m, _)) = Map.lookupMin m---- | /O(log n)/. Return the largest key and the associated values. Returns 'Nothing'--- if the map is empty.------ > lookupMax (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (2, Set.fromList "c")--- > lookupMax (empty :: SetMultimap Int Char) === Nothing-lookupMax :: SetMultimap k a -> Maybe (k, Set a)-lookupMax (SetMultimap (m, _)) = Map.lookupMax m---- | /O(log n)/. Return the largest key smaller than the given one, and the associated--- values, if exist.------ > lookupLT 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing--- > lookupLT 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")-lookupLT :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)-lookupLT k (SetMultimap (m, _)) = Map.lookupLT k m---- | /O(log n)/. Return the smallest key larger than the given one, and the associated--- values, if exist.------ > lookupGT 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing--- > lookupGT 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")-lookupGT :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)-lookupGT k (SetMultimap (m, _)) = Map.lookupGT k m---- | /O(log n)/. Return the largest key smaller than or equal to the given one, and the associated--- values, if exist.------ > lookupLE 0 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing--- > lookupLE 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (1, Set.fromList "a")--- > lookupLE 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")-lookupLE :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)-lookupLE k (SetMultimap (m, _)) = Map.lookupLE k m---- | /O(log n)/. Return the smallest key larger than or equal to the given one, and the associated--- values, if exist.+-- | Convert a t'Data.Multimap.Multimap' to a t'Data.Multimap.Set.SetMultimap'. ----- > lookupGE 6 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing--- > lookupGE 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (5, Set.fromList "c")--- > lookupGE 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")-lookupGE :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)-lookupGE k (SetMultimap (m, _)) = Map.lookupGE k m----------------------------------------------------------------------------------- * Non exported functions---------------------------------------------------------------------------------catMaybes :: Ord a => Set (Maybe a) -> Set a-catMaybes = Set.foldl' (\s -> maybe s (`Set.insert` s)) Set.empty--partitionEithers :: (Ord a, Ord b) => Set (Either a b) -> (Set a, Set b)-partitionEithers = Set.foldr' (either left right) (Set.empty, Set.empty)-  where-    left a (l,r) = (Set.insert a l, r)-    right b (l,r) = (l, Set.insert b r)--fromMap' :: Ord k => k -> Map k (Set a) -> SetMultimap k a-fromMap' k m = SetMultimap (m', sum (fmap Set.size m'))-  where-    m' = case Map.lookup k m of-      Just as | Set.null as -> Map.delete k m-      _ -> m+-- > fromMultimap (Data.Multimap.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]+fromMultimap :: Ord a => Multimap k a -> SetMultimap k a+fromMultimap = toSetMultimap
+ src/Data/Multimap/Set/Internal.hs view
@@ -0,0 +1,731 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  Data.Multimap.Set.Internal+-- Maintainer  :  Ziyang Liu <free@cofree.io>+--+module Data.Multimap.Set.Internal (+  -- * Multimap type+  SetMultimap (..)+  , Size++  -- * Construction+  , empty+  , singleton+  , fromMap++  -- ** From Unordered Lists+  , fromList++  -- * Insertion+  , insert++  -- * Deletion\/Update+  , delete+  , deleteWithValue+  , deleteMax+  , deleteMin+  , adjust+  , adjustWithKey+  , update+  , updateWithKey+  , alter+  , alterWithKey++  -- * Query+  -- ** Lookup+  , lookup+  , (!)+  , member+  , notMember++  -- ** Size+  , null+  , notNull+  , size++  -- * Combine+  -- ** Union+  , union+  , unions++  -- ** Difference+  , difference++  -- * Traversal+  -- ** Map+  , map+  , mapWithKey++  -- ** Folds+  , foldr+  , foldl+  , foldrWithKey+  , foldlWithKey+  , foldMapWithKey++  -- ** Strict Folds+  , foldr'+  , foldl'+  , foldrWithKey'+  , foldlWithKey'++  -- * Conversion+  , elems+  , keys+  , assocs+  , keysSet++  -- ** Lists+  , toList++  -- ** Ordered lists+  , toAscList+  , toDescList++  -- ** Maps+  , toMap++  -- * Filter+  , filter+  , filterWithKey+  , filterKey+  , filterM+  , filterWithKeyM++  , mapMaybe+  , mapMaybeWithKey+  , mapEither+  , mapEitherWithKey++  -- * Min\/Max+  , lookupMin+  , lookupMax+  , lookupLT+  , lookupGT+  , lookupLE+  , lookupGE+  ) where++import Prelude hiding (filter, foldl, foldr, lookup, map, null)++import           Control.Arrow ((&&&))+import qualified Control.Monad as List (filterM)+import           Data.Data (Data)+import qualified Data.Foldable as Foldable+import           Data.Functor.Classes+import           Data.Map.Lazy (Map)+import qualified Data.Map.Lazy as Map+import qualified Data.Maybe as Maybe+import           Data.Set (Set)+import qualified Data.Set as Set++infixl 9 !++type Size = Int++newtype SetMultimap k a = SetMultimap (Map k (Set a), Size)+  deriving (Eq, Ord, Data)++instance Eq k => Eq1 (SetMultimap k) where+  liftEq = liftEq2 (==)++instance Eq2 SetMultimap where+  liftEq2 eqk eqv m n =+    Map.size (toMap m) == Map.size (toMap n)+      && liftEq (liftEq2 eqk eqv) (toList m) (toList n)++instance Ord k => Ord1 (SetMultimap k) where+  liftCompare = liftCompare2 compare++instance Ord2 SetMultimap where+  liftCompare2 cmpk cmpv m n =+      liftCompare (liftCompare2 cmpk cmpv) (toList m) (toList n)++instance (Show k, Show a) => Show (SetMultimap k a) where+  showsPrec d m = showParen (d > 10) $+    showString "fromList " . shows (toList m)++instance Show k => Show1 (SetMultimap k) where+  liftShowsPrec = liftShowsPrec2 showsPrec showList++instance Show2 SetMultimap where+  liftShowsPrec2 spk slk spv slv d m =+      showsUnaryWith (liftShowsPrec sp sl) "fromList" d (toList m)+    where+      sp = liftShowsPrec2 spk slk spv slv+      sl = liftShowList2 spk slk spv slv++instance (Ord k, Ord a, Read k, Read a) => Read (SetMultimap k a) where+  readsPrec p = readParen (p > 10) $ \ r -> do+    ("fromList",s) <- lex r+    (xs,t) <- reads s+    pure (fromList xs,t)++instance Foldable.Foldable (SetMultimap k) where+  foldMap = foldMapWithKey . const+  {-# INLINE foldMap #-}++instance (Ord k, Ord a) => Semigroup (SetMultimap k a) where+  (<>) = union++instance (Ord k, Ord a) => Monoid (SetMultimap k a) where+  mempty = empty+  mappend = (<>)++------------------------------------------------------------------------------++-- | /O(1)/. The empty multimap.+--+-- > size empty === 0+empty :: SetMultimap k a+empty = SetMultimap (Map.empty, 0)++-- | /O(1)/. A multimap with a single element.+--+-- > singleton 1 'a' === fromList [(1, 'a')]+-- > size (singleton 1 'a') === 1+singleton :: k -> a -> SetMultimap k a+singleton k a = SetMultimap (Map.singleton k (Set.singleton a), 1)++-- | /O(n*log n)/ where /n/ is the length of the input list.+--  Build a multimap from a list of key\/value pairs.+--+-- > fromList ([] :: [(Int, Char)]) === empty+-- > fromList [(1, 'b'), (2, 'a'), (1, 'b')] === fromList [(1, 'b'), (2, 'a')]+fromList :: (Ord k, Ord a) => [(k, a)] -> SetMultimap k a+fromList = Foldable.foldr (uncurry insert) empty++-- | /O(k)/. A key is retained only if it is associated with a+-- non-empty set of values.+fromMap :: Map k (Set a) -> SetMultimap k a+fromMap m = SetMultimap (m', sum (fmap Set.size m'))+  where+    m' = Map.filter (not . Set.null) m++------------------------------------------------------------------------------++-- | /O(log m * log k)/. If the key exists in the multimap, the new value will+-- be inserted into the set of values for the key. It is a no-op if the value+-- already exists in the set.+--+-- > insert 1 'a' empty === singleton 1 'a'+-- > insert 1 'a' (fromList [(1, 'b'), (2, 'a')]) === fromList [(1, 'a'), (1, 'b'), (2, 'a')]+-- > insert 1 'a' (fromList [(1, 'a'), (2, 'c')]) === fromList [(1, 'a'), (2, 'c')]+insert :: (Ord k, Ord a) => k -> a -> SetMultimap k a -> SetMultimap k a+insert k a (SetMultimap (m, _)) = fromMap' k (Map.alter f k m)+  where+    f (Just as) = Just (Set.insert a as)+    f Nothing = Just (Set.singleton a)++-- | /O(log k)/. Delete a key and all its values from the map.+--+-- > delete 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === singleton 2 'c'+delete :: Ord k => k -> SetMultimap k a -> SetMultimap k a+delete = alter (const Set.empty)++-- | /O(log m * log k)/. Remove the first+-- occurrence of the value associated with the key, if exists.+--+-- > deleteWithValue 1 'c' (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]+-- > deleteWithValue 1 'c' (fromList [(2,'c'),(1,'c')]) === singleton 2 'c'+deleteWithValue :: (Ord k, Ord a) => k -> a -> SetMultimap k a -> SetMultimap k a+deleteWithValue k a = alter (Set.delete a) k++-- | /O(log m * log k)/. Remove the maximal value+-- associated with the key, if exists.+--+-- > deleteMax 3 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]+-- > deleteMax 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(2,'c')]+deleteMax :: Ord k => k -> SetMultimap k a -> SetMultimap k a+deleteMax = alter Set.deleteMax++-- | /O(log m * log k)/. Remove the minimal value+-- associated with the key, if exists.+--+-- > deleteMin 3 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]+-- > deleteMin 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'b'),(2,'c')]+deleteMin :: Ord k => k -> SetMultimap k a -> SetMultimap k a+deleteMin = alter Set.deleteMin++-- | /O(m * log m * log k)/, assuming the function @a -> a@ takes /O(1)/.+-- Update values at a specific key, if exists.+--+-- Since values are sets, the result may be smaller than the original multimap.+--+-- > adjust ("new " ++) 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(1,"new b"),(2,"c")]+-- > adjust (const "z") 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"z"),(2,"c")]+adjust :: (Ord k, Ord a) => (a -> a) -> k -> SetMultimap k a -> SetMultimap k a+adjust = adjustWithKey. const++-- | /O(m * log m * log k)/, assuming the function @k -> a -> a@ takes /O(1)/.+-- Update values at a specific key, if exists.+--+-- Since values are sets, the result may be smaller than the original multimap.+--+-- > adjustWithKey (\k x -> show k ++ ":new " ++ x) 1 (fromList [(1,"a"),(1,"b"),(2,"c")])+-- >   === fromList [(1,"1:new a"),(1,"1:new b"),(2,"c")]+adjustWithKey :: (Ord k, Ord a) => (k -> a -> a) -> k -> SetMultimap k a -> SetMultimap k a+adjustWithKey f = alterWithKey (Set.map . f)++-- | /O(m * log m * log k)/, assuming the function @a -> 'Maybe' a@+-- takes /O(1)/. The expression (@'update' f k map@) updates the+-- values at key @k@, if exists. If @f@ returns 'Nothing' for a value, the+-- value is deleted.+--+-- > let f x = if x == "a" then Just "new a" else Nothing in do+-- >   update f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(2, "c")]+-- >   update f 1 (fromList [(1,"b"),(1,"c"),(2,"c")]) === singleton 2 "c"+update :: (Ord k, Ord a) => (a -> Maybe a) -> k -> SetMultimap k a -> SetMultimap k a+update = updateWithKey . const++-- | /O(m * log m * log k)/, assuming the function @k -> a -> 'Maybe' a@+-- takes /O(1)/. The expression (@'updateWithKey' f k map@) updates the+-- values at key @k@, if exists. If @f@ returns 'Nothing' for a value, the+-- value is deleted.+--+-- > let f k x = if x == "a" then Just (show k ++ ":new a") else Nothing in do+-- >   updateWithKey f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"1:new a"),(2,"c")]+-- >   updateWithKey f 1 (fromList [(1,"b"),(1,"c"),(2,"c")]) === singleton 2 "c"+updateWithKey :: (Ord k, Ord a) => (k -> a -> Maybe a) -> k -> SetMultimap k a -> SetMultimap k a+updateWithKey f = alterWithKey g+  where+    g k = catMaybes . Set.map (f k)++-- | /O(log k)/, assuming the function @'Set' a -> 'Set' a@ takes /O(1)/.+-- The expression (@'alter' f k map@) alters the values at k, if exists.+--+-- > let (f, g) = (const Set.empty, Set.insert 'c') in do+-- >   alter f 1 (fromList [(1, 'a'), (2, 'b')]) === singleton 2 'b'+-- >   alter f 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b')]+-- >   alter g 1 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'c'), (1, 'a'), (2, 'b')]+-- >   alter g 1 (fromList [(1, 'c'), (2, 'b')]) === fromList [(1, 'c'), (2, 'b')]+-- >   alter g 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b'), (3, 'c')]+alter :: Ord k => (Set a -> Set a) -> k -> SetMultimap k a -> SetMultimap k a+alter = alterWithKey . const++-- | /O(log k)/, assuming the function @k -> 'Set' a -> 'Set' a@ takes /O(1)/.+-- The expression (@'alterWithKey' f k map@) alters the values at k, if exists.+--+-- > let (f, g) = (const (const Set.empty), Set.insert . show) in do+-- >   alterWithKey f 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"+-- >   alterWithKey f 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b")]+-- >   alterWithKey g 1 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "1"), (1, "a"), (2, "b")]+-- >   alterWithKey g 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b"), (3, "3")]+alterWithKey :: Ord k => (k -> Set a -> Set a) -> k -> SetMultimap k a -> SetMultimap k a+alterWithKey f k mm@(SetMultimap (m, _))+    | Set.null as = fromMap (Map.delete k m)+    | otherwise = fromMap (Map.insert k as m)+  where+    as = f k (mm ! k)++------------------------------------------------------------------------------++-- | /O(log k)/. Lookup the values at a key in the map. It returns an empty+-- set if the key is not in the map.+lookup :: Ord k => k -> SetMultimap k a -> Set a+lookup k (SetMultimap (m, _)) = Maybe.fromMaybe Set.empty (Map.lookup k m)++-- | /O(log k)/. Lookup the values at a key in the map. It returns an empty+-- set if the key is not in the map.+--+-- > fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 3 === Set.fromList "ac"+-- > fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 2 === Set.empty+(!) :: Ord k => SetMultimap k a -> k -> Set a+(!) = flip lookup++-- | /O(log k)/. Is the key a member of the map?+--+-- A key is a member of the map if and only if there is at least one value+-- associated with it.+--+-- > member 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === True+-- > member 1 (deleteMax 1 (fromList [(2, 'c'), (1, 'c')])) === False+member :: Ord k => k -> SetMultimap k a -> Bool+member k (SetMultimap (m, _)) = Map.member k m++-- | /O(log k)/. Is the key not a member of the map?+--+-- A key is a member of the map if and only if there is at least one value+-- associated with it.+--+-- > notMember 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === False+-- > notMember 1 (deleteMin 1 (fromList [(2, 'c'), (1, 'c')])) === True+notMember :: Ord k => k -> SetMultimap k a -> Bool+notMember k = not . member k++-- | /O(1)/. Is the multimap empty?+--+-- > Data.Multimap.Set.null empty === True+-- > Data.Multimap.Set.null (singleton 1 'a') === False+null :: SetMultimap k a -> Bool+null (SetMultimap (m, _)) = Map.null m++-- | /O(1)/. Is the multimap non-empty?+--+-- > notNull empty === False+-- > notNull (singleton 1 'a') === True+notNull :: SetMultimap k a -> Bool+notNull = not . null++-- | The total number of values for all keys.+--+-- @size@ is evaluated lazily. Forcing the size for the first time takes up to+-- /O(k)/ and subsequent forces take /O(1)/.+--+-- > size empty === 0+-- > size (singleton 1 'a') === 1+-- > size (fromList [(1, 'a'), (2, 'b'), (2, 'c'), (2, 'b')]) === 3+size :: SetMultimap k a -> Int+size (SetMultimap (_, sz)) = sz++------------------------------------------------------------------------------++-- | Union two multimaps, unioning values for duplicate keys.+--+-- > union (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b')])+-- >   === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c')]+union :: (Ord k, Ord a) => SetMultimap k a -> SetMultimap k a -> SetMultimap k a+union (SetMultimap (m1, _)) (SetMultimap (m2, _)) =+  fromMap (Map.unionWith Set.union m1 m2)++-- | Union a number of multimaps, unioning values for duplicate keys.+--+-- > unions [fromList [(1,'a'),(2,'b'),(2,'c')], fromList [(1,'d'),(2,'b')]]+-- >   === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c')]+unions :: (Foldable f, Ord k, Ord a) => f (SetMultimap k a) -> SetMultimap k a+unions = Foldable.foldr union empty++-- | Difference of two multimaps.+--+-- If a key exists in the first multimap but not the second, it remains+-- unchanged in the result. If a key exists in both multimaps, a set+-- difference is performed on their values.+--+-- > difference (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b'),(2,'a')])+-- >   === fromList [(1,'a'),(2,'c')]+difference :: (Ord k, Ord a) => SetMultimap k a -> SetMultimap k a -> SetMultimap k a+difference (SetMultimap (m1, _)) (SetMultimap (m2, _)) = fromMap $+  Map.differenceWith (\xs ys -> Just (xs Set.\\ ys)) m1 m2++------------------------------------------------------------------------------++-- | /O(n * log m)/, assuming the function @a -> b@ takes /O(1)/.+-- Map a function over all values in the map.+--+-- Since values are sets, the result may be smaller than the original multimap.+--+-- > Data.Multimap.Set.map (++ "x") (fromList [(1,"a"),(2,"b")]) === fromList [(1,"ax"),(2,"bx")]+-- > Data.Multimap.Set.map (const "c") (fromList [(1,"a"),(1,"b"),(2,"b")]) === fromList [(1,"c"),(2,"c")]+map :: Ord b => (a -> b) -> SetMultimap k a -> SetMultimap k b+map = mapWithKey . const++-- | /O(n * log m)/, assuming the function @k -> a -> b@ takes /O(1)/.+-- Map a function over all values in the map.+--+-- Since values are sets, the result may be smaller than the original multimap.+--+-- > mapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1,"a"),(2,"b")]) === fromList [(1,"1:a"),(2,"2:b")]+mapWithKey :: Ord b => (k -> a -> b) -> SetMultimap k a -> SetMultimap k b+mapWithKey f (SetMultimap (m, _)) = fromMap $ Map.mapWithKey (Set.map . f) m++-- | /O(n)/. Fold the values in the map using the given right-associative+-- binary operator.+--+-- > Data.Multimap.Set.foldr ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+foldr :: (a -> b -> b) -> b -> SetMultimap k a -> b+foldr = foldrWithKey . const++-- | /O(n)/. Fold the values in the map using the given left-associative+-- binary operator.+--+-- > Data.Multimap.Set.foldl (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+foldl :: (a -> b -> a) -> a -> SetMultimap k b -> a+foldl = foldlWithKey . (const .)++-- | /O(n)/. Fold the key\/value pairs in the map using the given+-- right-associative binary operator.+--+-- > foldrWithKey (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+foldrWithKey :: (k -> a -> b -> b) -> b -> SetMultimap k a -> b+foldrWithKey f b (SetMultimap (m, _)) = Map.foldrWithKey f' b m+  where+    f' = flip . Set.foldr . f++-- | /O(n)/. Fold the key\/value pairs in the map using the given+-- left-associative binary operator.+--+-- > foldlWithKey (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+foldlWithKey :: (a -> k -> b -> a) -> a -> SetMultimap k b -> a+foldlWithKey f a (SetMultimap (m, _)) = Map.foldlWithKey f' a m+  where+    f' = flip (Set.foldl . flip f)++-- | /O(n)/. A strict version of 'foldr'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > Data.Multimap.Set.foldr' ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+foldr' :: (a -> b -> b) -> b -> SetMultimap k a -> b+foldr' = foldrWithKey' . const++-- | /O(n)/. A strict version of 'foldl'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > Data.Multimap.Set.foldl' (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+foldl' :: (a -> b -> a) -> a -> SetMultimap k b -> a+foldl' = foldlWithKey' . (const .)++-- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > foldrWithKey' (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+foldrWithKey' :: (k -> a -> b -> b) -> b -> SetMultimap k a -> b+foldrWithKey' f b (SetMultimap (m, _)) = Map.foldrWithKey f' b m+  where+    f' = flip . Set.foldr' . f++-- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > foldlWithKey' (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+foldlWithKey' :: (a -> k -> b -> a) -> a -> SetMultimap k b -> a+foldlWithKey' f a (SetMultimap (m, _)) = Map.foldlWithKey f' a m+  where+    f' = flip (Set.foldl' . flip f)++-- | /O(n)/. Fold the key\/value pairs in the map using the given monoid.+--+-- > foldMapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1, "a"), (1, "c"), (2, "b")]) === "1:a1:c2:b"+foldMapWithKey :: Monoid m => (k -> a -> m) -> SetMultimap k a -> m+foldMapWithKey f (SetMultimap (m, _)) = Map.foldMapWithKey f' m+  where+    f' = Foldable.foldMap . f++------------------------------------------------------------------------------++-- | /O(n)/. Return all elements of the multimap in ascending order of+-- their keys. Elements of each key appear in ascending order.+--+-- > elems (fromList [(2,'a'),(1,'b'),(3,'d'),(3,'c'),(1,'b')]) === "bacd"+-- > elems (empty :: SetMultimap Int Char) === []+elems :: SetMultimap k a -> [a]+elems (SetMultimap (m, _)) = Map.elems m >>= Set.toList++-- | /O(k)/. Return all keys of the multimap in ascending order.+--+-- > keys (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'b')]) === [1,2,3]+-- > keys (empty :: SetMultimap Int Char) === []+keys :: SetMultimap k a -> [k]+keys (SetMultimap (m, _)) = Map.keys m++-- | /O(k)/. The set of all keys of the multimap.+--+-- > keysSet (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'b')]) === Set.fromList [1,2,3]+-- > keysSet (empty :: SetMultimap Int Char) === Set.empty+keysSet :: SetMultimap k a -> Set k+keysSet (SetMultimap (m, _)) = Map.keysSet m++-- | An alias for 'toAscList'.+assocs :: SetMultimap k a -> [(k, a)]+assocs = toAscList++-- | Convert the multimap into a list of key/value pairs.+--+-- > toList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'a'),(1,'b'),(2,'a'),(3,'c')]+toList :: SetMultimap k a -> [(k, a)]+toList = toAscList++-- | Convert the multimap into a list of key/value pairs in ascending+-- order of keys. Elements of each key appear in ascending order.+--+-- > toAscList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'a'),(1,'b'),(2,'a'),(3,'c')]+toAscList :: SetMultimap k a -> [(k, a)]+toAscList (SetMultimap (m, _)) =+  Map.toAscList m >>= uncurry (\k -> fmap (k,) . Set.toAscList)++-- | Convert the multimap into a list of key/value pairs in descending+-- order of keys. Elements of each key appear in descending order.+--+-- > toDescList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(3,'c'),(2,'a'),(1,'b'),(1,'a')]+toDescList :: SetMultimap k a -> [(k, a)]+toDescList (SetMultimap (m, _)) =+  Map.toDescList m >>= uncurry (\k -> fmap (k,) . Set.toDescList)++-- | /O(1)/. Convert the multimap into a regular map.+toMap :: SetMultimap k a -> Map k (Set a)+toMap (SetMultimap (m, _)) = m++------------------------------------------------------------------------------++-- | /O(n)/, assuming the predicate function takes /O(1)/.+-- Retain all values that satisfy the predicate. A key is removed if+-- none of its values satisfies the predicate.+--+-- > Data.Multimap.Set.filter (> 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 1 'b'+-- > Data.Multimap.Set.filter (< 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === empty+filter :: (a -> Bool) -> SetMultimap k a -> SetMultimap k a+filter = filterWithKey . const++-- | /O(k)/, assuming the predicate function takes /O(1)/.+-- Retain all keys that satisfy the predicate.+filterKey :: (k -> Bool) -> SetMultimap k a -> SetMultimap k a+filterKey p (SetMultimap (m, _)) = fromMap m'+  where+    m' = Map.filterWithKey (const . p) m++-- | /O(n)/, assuming the predicate function takes /O(1)/.+-- Retain all key\/value pairs that satisfy the predicate. A key is removed if+-- none of its values satisfies the predicate.+--+-- > filterWithKey (\k a -> even k && a > 'a') (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'b')]) === singleton 2 'b'+filterWithKey :: (k -> a -> Bool) -> SetMultimap k a -> SetMultimap k a+filterWithKey p (SetMultimap (m, _)) = fromMap m'+  where+    m' = Map.mapWithKey (Set.filter . p) m++-- | Generalized 'filter'.+--+-- > let f a | a > 'b' = Just True+-- >         | a < 'b' = Just False+-- >         | a == 'b' = Nothing+-- >  in do+-- >    filterM f (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'c')]) === Nothing+-- >    filterM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Just (fromList [(1,'c'),(2,'c')])+filterM+  :: (Ord k, Ord a, Applicative t)+  => (a -> t Bool) -> SetMultimap k a -> t (SetMultimap k a)+filterM = filterWithKeyM . const++-- | Generalized 'filterWithKey'.+-- | Generalized 'filterWithKey'.+--+-- > let f k a | even k && a > 'b' = Just True+-- >           | odd k && a < 'b' = Just False+-- >           | otherwise = Nothing+-- >  in do+-- >    filterWithKeyM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Nothing+-- >    filterWithKeyM f (fromList [(1,'a'),(3,'a'),(2,'c'),(4,'c')]) === Just (fromList [(2,'c'),(4,'c')])+filterWithKeyM+  :: (Ord k, Ord a, Applicative t)+  => (k -> a -> t Bool) -> SetMultimap k a -> t (SetMultimap k a)+filterWithKeyM f = fmap fromList . List.filterM (uncurry f) . toList++-- | /O(n * log m)/, assuming the function @a -> 'Maybe' b@ takes /O(1)/.+-- Map values and collect the 'Just' results.+--+-- > mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])+-- >   === fromList [(1,"new a"),(2,"new a")]+mapMaybe :: Ord b => (a -> Maybe b) -> SetMultimap k a -> SetMultimap k b+mapMaybe = mapMaybeWithKey . const++-- | /O(n * log m)/, assuming the function @k -> a -> 'Maybe' b@ takes /O(1)/.+-- Map key\/value pairs and collect the 'Just' results.+--+-- > mapMaybeWithKey (\k a -> if k > 1 && a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])+-- >   === singleton 2 "new a"+mapMaybeWithKey :: Ord b => (k -> a -> Maybe b) -> SetMultimap k a -> SetMultimap k b+mapMaybeWithKey f (SetMultimap (m, _)) = fromMap $+  Map.mapWithKey (\k -> catMaybes . Set.map (f k)) m++-- | /O(n * log m)/, assuming the function @a -> 'Either' b c@ takes /O(1)/.+-- Map values and separate the 'Left' and 'Right' results.+--+-- > mapEither (\a -> if a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])+-- >   === (fromList [(1,'a'),(2,'a')],fromList [(1,'c'),(2,'c')])+mapEither+  :: (Ord b, Ord c)+  => (a -> Either b c) -> SetMultimap k a -> (SetMultimap k b, SetMultimap k c)+mapEither = mapEitherWithKey . const++-- | /O(n * log m)/, assuming the function @k -> a -> 'Either' b c@ takes /O(1)/.+-- Map key\/value pairs and separate the 'Left' and 'Right' results.+--+-- > mapEitherWithKey (\k a -> if even k && a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])+-- >   === (fromList [(2,'a')],fromList [(1,'a'),(1,'c'),(2,'c')])+mapEitherWithKey+  :: (Ord b, Ord c)+  => (k -> a -> Either b c) -> SetMultimap k a -> (SetMultimap k b, SetMultimap k c)+mapEitherWithKey f (SetMultimap (m, _)) =+  (fromMap . Map.mapWithKey (const fst) &&& fromMap . Map.mapWithKey (const snd))+      $ Map.mapWithKey g m+  where+    g k = partitionEithers . Set.map (f k)++------------------------------------------------------------------------------++-- | /O(log n)/. Return the smallest key and the associated values. Returns 'Nothing'+-- if the map is empty.+--+-- > lookupMin (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (1, Set.fromList "ac")+-- > lookupMin (empty :: SetMultimap Int Char) === Nothing+lookupMin :: SetMultimap k a -> Maybe (k, Set a)+lookupMin (SetMultimap (m, _)) = Map.lookupMin m++-- | /O(log n)/. Return the largest key and the associated values. Returns 'Nothing'+-- if the map is empty.+--+-- > lookupMax (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (2, Set.fromList "c")+-- > lookupMax (empty :: SetMultimap Int Char) === Nothing+lookupMax :: SetMultimap k a -> Maybe (k, Set a)+lookupMax (SetMultimap (m, _)) = Map.lookupMax m++-- | /O(log n)/. Return the largest key smaller than the given one, and the associated+-- values, if exist.+--+-- > lookupLT 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+-- > lookupLT 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")+lookupLT :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)+lookupLT k (SetMultimap (m, _)) = Map.lookupLT k m++-- | /O(log n)/. Return the smallest key larger than the given one, and the associated+-- values, if exist.+--+-- > lookupGT 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+-- > lookupGT 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")+lookupGT :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)+lookupGT k (SetMultimap (m, _)) = Map.lookupGT k m++-- | /O(log n)/. Return the largest key smaller than or equal to the given one, and the associated+-- values, if exist.+--+-- > lookupLE 0 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+-- > lookupLE 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (1, Set.fromList "a")+-- > lookupLE 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")+lookupLE :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)+lookupLE k (SetMultimap (m, _)) = Map.lookupLE k m++-- | /O(log n)/. Return the smallest key larger than or equal to the given one, and the associated+-- values, if exist.+--+-- > lookupGE 6 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+-- > lookupGE 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (5, Set.fromList "c")+-- > lookupGE 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")+lookupGE :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)+lookupGE k (SetMultimap (m, _)) = Map.lookupGE k m++------------------------------------------------------------------------------+-- * Non exported functions+------------------------------------------------------------------------------++catMaybes :: Ord a => Set (Maybe a) -> Set a+catMaybes = Set.foldl' (\s -> maybe s (`Set.insert` s)) Set.empty++partitionEithers :: (Ord a, Ord b) => Set (Either a b) -> (Set a, Set b)+partitionEithers = Set.foldr' (either left right) (Set.empty, Set.empty)+  where+    left a (l,r) = (Set.insert a l, r)+    right b (l,r) = (l, Set.insert b r)++fromMap' :: Ord k => k -> Map k (Set a) -> SetMultimap k a+fromMap' k m = SetMultimap (m', sum (fmap Set.size m'))+  where+    m' = case Map.lookup k m of+      Just as | Set.null as -> Map.delete k m+      _ -> m
src/Data/Multimap/Table.hs view
@@ -1,6 +1,3 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE TypeFamilies #-}- ----------------------------------------------------------------------------- -- | -- Module      :  Data.Multimap.Table@@ -125,704 +122,5 @@   , mapEitherWithKeys   ) where -import           Control.Arrow ((&&&))-import           Data.Data (Data)-import qualified Data.Foldable as Foldable-import           Data.Map (Map)-import qualified Data.Map as Map-import qualified Data.Maybe as Maybe-import           Data.Set (Set)-+import Data.Multimap.Table.Internal import Prelude hiding (filter, foldl, foldr, lookup, map, null)--infixl 9 !,!?--type Size = Int--newtype Table r c a = Table (Map r (Map c a), Map c (Map r a), Size)-  deriving (Eq, Ord, Data)--instance (Show r, Show c, Show a) => Show (Table r c a) where-  showsPrec d m = showParen (d > 10) $-    showString "fromList " . shows (toList m)--instance (Ord r, Ord c, Read r, Read c, Read a) => Read (Table r c a) where-  readsPrec p = readParen (p > 10) $ \ r -> do-    ("fromList",s) <- lex r-    (xs,t) <- reads s-    pure (fromList xs,t)--instance Functor (Table r c) where-  fmap = map--instance Foldable.Foldable (Table r c) where-  foldMap = foldMapWithKeys . const . const-  {-# INLINE foldMap #-}--instance (Ord r, Ord c) => Traversable (Table r c) where-  traverse = traverseWithKeys . const . const-  {-# INLINE traverse #-}--instance (Ord r, Ord c) => Semigroup (Table r c a) where-  (<>) = union--instance (Ord r, Ord c) => Monoid (Table r c a) where-  mempty = empty-  mappend = (<>)------------------------------------------------------------------------------------ | /O(1)/. The empty table.------ > size empty === 0-empty :: Table r c a-empty = Table (Map.empty, Map.empty, 0)---- | /O(1)/. A table with a single element.------ > singleton 1 'a' "a" === fromList [(1,'a',"a")]--- > size (singleton 1 'a' "a") === 1-singleton :: r -> c -> a -> Table r c a-singleton r c a = Table (Map.singleton r (Map.singleton c a), Map.singleton c (Map.singleton r a), 1)---- | Build a table from a list of key\/value pairs.------ > fromList ([] :: [(Int, Char, String)]) === empty-fromList :: (Ord r, Ord c) => [(r, c, a)] -> Table r c a-fromList = Foldable.foldr (uncurry3 insert) empty---- | Build a table from a row map.------ > fromRowMap (Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]), (2, Map.fromList [('a',"d")])])--- >   === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-fromRowMap :: (Ord r, Ord c) => Map r (Map c a) -> Table r c a-fromRowMap m = Table (m', transpose' m', size' m')-  where m' = nonEmpty m---- | Build a table from a column map.------ > fromColumnMap (Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]), (2, Map.fromList [('a',"d")])])--- >   === fromList [('a',1,"b"),('a',2,"d"),('b',1,"c")]-fromColumnMap :: (Ord r, Ord c) => Map c (Map r a) -> Table r c a-fromColumnMap m = Table (transpose' m', m', size' m')-  where m' = nonEmpty m---- | Flip the row and column keys.------ > transpose (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [('a',1,"b"),('a',2,"d"),('b',1,"c")]-transpose :: Table r c a -> Table c r a-transpose (Table (rm, cm, sz)) = Table (cm, rm, sz)------------------------------------------------------------------------------------ | /O(log k)/. Associate with value with the row key and the column key.--- If the table already contains a value for those keys, the value is replaced.------ > insert 1 'a' "a" empty === singleton 1 'a' "a"--- > insert 1 'a' "a" (fromList [(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"d")]--- > insert 1 'a' "a" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"d")]-insert :: (Ord r, Ord c) => r -> c -> a -> Table r c a -> Table r c a-insert r c a (Table (rm, cm, _)) = fromMaps' r c rm' cm'-  where-    rm' = Map.alter f r rm-    cm' = Map.alter g c cm-    f = Just . maybe (Map.singleton c a) (Map.insert c a)-    g = Just . maybe (Map.singleton r a) (Map.insert r a)---- | /O(log k)/. Remove the value associated with the given keys.------ > delete 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'b',"c"),(2,'a',"d")]--- > delete 1 'a' (fromList [(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'b',"c"),(2,'a',"d")]-delete :: (Ord r, Ord c) => r -> c -> Table r c a -> Table r c a-delete r c (Table (rm, cm, _)) = fromMaps' r c rm' cm'-  where-    rm' = Map.adjust (Map.delete c) r rm-    cm' = Map.adjust (Map.delete r) c cm---- | Remove an entire row.------ > deleteRow 1 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"--- > deleteRow 3 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-deleteRow :: Ord r => r -> Table r c a -> Table r c a-deleteRow r (Table (rm, cm, _)) = Table (rm', cm', size' rm')-  where-    rm' = Map.delete r rm-    cm' = nonEmpty $ Map.map (Map.delete r) cm---- | Remove an entire column.------ > deleteColumn 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"--- > deleteColumn 'z' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-deleteColumn :: Ord c => c -> Table r c a -> Table r c a-deleteColumn c (Table (rm, cm, _)) = Table (rm', cm', size' cm')-  where-    rm' = nonEmpty $ Map.map (Map.delete c) rm-    cm' = Map.delete c cm---- | /O(log k)/, assuming the function @a -> a@ takes /O(1)/.--- Update the value at a specific row key and column key, if exists.------ > adjust ("new " ++) 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"new b"),(1,'b',"c"),(2,'a',"d")]-adjust :: (Ord r, Ord c) => (a -> a) -> r -> c -> Table r c a -> Table r c a-adjust = adjustWithKeys . const . const---- | /O(log k)/, assuming the function @r -> c -> a -> a@ takes /O(1)/.--- Update the value at a specific row key and column key, if exists.------ > adjustWithKeys (\r c x -> show r ++ ":" ++ show c ++ ":new " ++ x) 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])--- >   === fromList [(1,'a',"1:'a':new b"),(1,'b',"c"),(2,'a',"d")]-adjustWithKeys-  :: (Ord r, Ord c)-  => (r -> c -> a -> a) -> r -> c -> Table r c a -> Table r c a-adjustWithKeys f = updateWithKeys (\r c a -> Just (f r c a))---- | /O(log k)/, assuming the function @a -> 'Maybe' a@ takes /O(1)/.--- The expression (@'update' f r c table@) updates the value at the given--- row and column keys, if exists. If @f@ returns 'Nothing', the value--- associated with those keys, if exists is deleted.------ > let f x = if x == "b" then Just "new b" else Nothing in do--- >   update f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"new b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   update f 1 'a' (fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-update :: (Ord r, Ord c) => (a -> Maybe a) -> r -> c -> Table r c a -> Table r c a-update = updateWithKeys . const . const---- | /O(log k)/, assuming the function @r -> c -> a -> 'Maybe' a@ takes /O(1)/.--- The expression (@'updateWithKeys' f r c table@) updates the value at the given--- row and column keys, if exists. If @f@ returns 'Nothing', the value--- associated with those keys, if exists is deleted.------ > let f r c x = if x == "b" then Just (show r ++ ":" ++ show c ++ ":new b") else Nothing in do--- >   updateWithKeys f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"1:'a':new b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   updateWithKeys f 1 'a' (fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-updateWithKeys-  :: (Ord r, Ord c)-  => (r -> c -> a -> Maybe a) -> r -> c -> Table r c a -> Table r c a-updateWithKeys f = alterWithKeys (\r c -> (>>= f r c))---- | /O(log k)/, assuming the function @'Maybe' a -> 'Maybe' a@ takes /O(1)/.--- The expression (@'alter' f r c table@) alters the value at the given--- row and column keys, if exists. It can be used to insert, delete--- or update a value.------ > let (f,g,h) = (const Nothing, const (Just "hello"), fmap ('z':)) in do--- >   alter f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   alter f 4 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   alter f 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   alter g 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"hello"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   alter g 4 'e' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c"),(4,'e',"hello")]--- >   alter h 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"zb"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   alter h 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-alter :: (Ord r, Ord c) => (Maybe a -> Maybe a) -> r -> c -> Table r c a -> Table r c a-alter = alterWithKeys . const . const---- | /O(log k)/, assuming the function @r -> c -> 'Maybe' a -> 'Maybe' a@ takes /O(1)/.--- The expression (@'alterWithKeys' f r c table@) alters the value at the given--- row and column keys, if exists. It can be used to insert, delete--- or update a value.------ > let (f,g) = (\_ _ _ -> Nothing, \r c -> fmap ((show r ++ ":" ++ show c ++ ":") ++)) in do--- >   alterWithKeys f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   alterWithKeys f 4 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   alterWithKeys f 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   alterWithKeys g 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"1:'a':b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]--- >   alterWithKeys g 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-alterWithKeys-  :: (Ord r, Ord c)-  => (r -> c -> Maybe a -> Maybe a) -> r -> c -> Table r c a -> Table r c a-alterWithKeys f r c tbl@(Table (rm, cm, _))-  | Just a <- f r c (lookup r c tbl) =-      let rm' = Map.alter (Just . maybe (Map.singleton c a) (Map.insert c a)) r rm-          cm' = Map.alter (Just . maybe (Map.singleton r a) (Map.insert r a)) c cm-       in fromMaps' r c rm' cm'-  | otherwise = delete r c tbl------------------------------------------------------------------------------------ | /O(log k)/. Lookup the values at a row key and column key in the map.-lookup :: (Ord r, Ord c) => r -> c -> Table r c a -> Maybe a-lookup r c (Table (rm, _, _)) = Map.lookup r rm >>= Map.lookup c---- | /O(log k)/. Lookup the values at a row key and column key in the map.------ > fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] !? (1,'a') === Just "b"--- > fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] !? (1,'c') === Nothing-(!?) :: (Ord r, Ord c) => Table r c a -> (r, c) -> Maybe a-(!?) = flip (uncurry lookup)---- | /O(log k)/. Lookup the values at a row key and column key in the map.--- Calls 'error' if the value does not exist.------ > fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] ! (1,'a') === "b"-(!) :: (Ord r, Ord c) => Table r c a -> (r, c) -> a-(!) tbl keys =-  Maybe.fromMaybe (error "Table.!: cell does not exist") (tbl !? keys)---- | /O(log k)/. Is there a value associated with the given row and--- column keys?------ > hasCell (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (1,'a') === True--- > hasCell (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (1,'c') === False-hasCell :: (Ord r, Ord c) => Table r c a -> (r, c) -> Bool-hasCell (Table (rm, _, _)) (r, c) =-  maybe False (Map.member c) (Map.lookup r rm)---- | /O(log r)/. Is there a row with the given row key that has at least---  one value?------ > hasRow (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 1 === True--- > hasRow (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 3 === False-hasRow :: Ord r => Table r c a -> r -> Bool-hasRow (Table (rm, _, _)) r = Map.member r rm---- | /O(log c)/. Is there a column with the given column key that has at least--- one value?------ > hasColumn (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 'a' === True--- > hasColumn (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 'c' === False-hasColumn :: Ord c => Table r c a -> c -> Bool-hasColumn (Table (_, cm, _)) c = Map.member c cm---- | /O(1)/. Is the table empty?------ > Data.Multimap.Table.null empty === True--- > Data.Multimap.Table.null (singleton 1 'a' "a") === False-null :: Table r c a -> Bool-null (Table (rm, _, _)) = Map.null rm---- | /O(1)/. Is the table non-empty?------ > notNull empty === False--- > notNull (singleton 1 'a' "a") === True-notNull :: Table r c a -> Bool-notNull = not . null---- | The total number of values for all row and column keys.------ @size@ is evaluated lazily. Forcing the size for the first time takes up to--- /O(n)/ and subsequent forces take /O(1)/.------ > size empty === 0--- > size (singleton 1 'a' "a") === 1--- > size (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === 3-size :: Table r c a -> Int-size (Table (_, _, sz)) = sz------------------------------------------------------------------------------------ | Union two tables, preferring values from the first table--- upon duplicate keys.------ > union (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])--- >   === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-union :: (Ord r, Ord c) => Table r c a -> Table r c a -> Table r c a-union = unionWith const---- | Union a number of tables, preferring values from the leftmost table--- upon duplicate keys.------ > unions [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]--- >   === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-unions :: (Foldable f, Ord r, Ord c) => f (Table r c a) -> Table r c a-unions = Foldable.foldr union empty---- | Union two tables with a combining function for duplicate keys.------ > unionWith (++) (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])--- >   === fromList [(1,'a',"bc"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-unionWith :: (Ord r, Ord c) => (a -> a -> a) -> Table r c a -> Table r c a -> Table r c a-unionWith = unionWithKeys . const . const---- | Union two tables with a combining function for duplicate keys.------ > let f r c a a' = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ a' in do--- >   unionWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])--- >     === fromList [(1,'a',"1:'a':b|c"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-unionWithKeys-  :: (Ord r, Ord c)-  => (r -> c -> a -> a -> a)-  -> Table r c a -> Table r c a -> Table r c a-unionWithKeys f (Table (rm1, cm1, _)) (Table (rm2, cm2, _)) = fromMaps rm cm-  where-    rm = Map.unionWithKey (Map.unionWithKey . f) rm1 rm2-    cm = Map.unionWithKey (Map.unionWithKey . flip f) cm1 cm2---- | Union a number of tables with a combining function for duplicate keys.------ > unionsWith (++) [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]--- >   === fromList [(1,'a',"bc"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-unionsWith :: (Foldable f, Ord r, Ord c) => (a -> a -> a) -> f (Table r c a) -> Table r c a-unionsWith f = Foldable.foldr (unionWith f) empty---- | Union a number of tables with a combining function for duplicate keys.------ > let f r c a a' = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ a' in do--- >   unionsWithKeys f [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]--- >     === fromList [(1,'a',"1:'a':b|c"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-unionsWithKeys-  :: (Foldable f, Ord r, Ord c)-  => (r -> c -> a -> a -> a)-  -> f (Table r c a) -> Table r c a-unionsWithKeys f = Foldable.foldr (unionWithKeys f) empty---- | Difference of two tables. Return values in the first table whose--- row and column keys do not have an associated value in the second table.------ > difference (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(1,'b',"d"),(2,'b',"b")])--- >   === singleton 2 'a' "b"-difference :: (Ord r, Ord c) => Table r c a -> Table r c a -> Table r c a-difference (Table (rm1, cm1, _)) (Table (rm2, cm2, _)) = fromMaps rm cm-  where-    rm = Map.differenceWith ((Just .) . Map.difference) rm1 rm2-    cm = Map.differenceWith ((Just .) . Map.difference) cm1 cm2------------------------------------------------------------------------------------ | /O(n)/, assuming the function @a -> b@ takes /O(1)/.--- Map a function over all values in the table.------ > Data.Multimap.Table.map (++ "x") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === fromList [(1,'a',"bx"),(1,'b',"cx"),(2,'a',"bx")]-map :: (a -> b) -> Table r c a -> Table r c b-map = mapWithKeys . const . const---- | /O(n)/, assuming the function @r -> c -> a -> b@ takes /O(1)/.--- Map a function over all values in the table.------ > mapWithKeys (\r c x -> show r ++ ":" ++ show c ++ ":" ++ x) (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")])--- >   === fromList [(1,'a',"1:'a':b"),(1,'b',"1:'b':c"),(2,'a',"2:'a':b")]-mapWithKeys :: (r -> c -> a -> b) -> Table r c a -> Table r c b-mapWithKeys f (Table (rm, cm, sz)) = Table (rm', cm', sz)-  where-    rm' = Map.mapWithKey (Map.mapWithKey . f) rm-    cm' = Map.mapWithKey (Map.mapWithKey . flip f) cm---- | Traverse the (row key, column key, value) triples and collect the results.------ > let f r c a = if odd r && c > 'a' then Just (a ++ "x") else Nothing in do--- >   traverseWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === Nothing--- >   traverseWithKeys f (fromList [(1,'b',"b"),(1,'c',"c"),(3,'d',"b")]) === Just (fromList [(1,'b',"bx"),(1,'c',"cx"),(3,'d',"bx")])-traverseWithKeys-  :: (Applicative t, Ord r, Ord c)-  => (r -> c -> a -> t b)-  -> Table r c a-  -> t (Table r c b)-traverseWithKeys f (Table (rm, _, _)) = fromMaps <$> rm' <*> cm'-  where-    rm' = Map.traverseWithKey (Map.traverseWithKey . f) rm-    cm' = transpose' <$> rm'---- | Traverse the (row key, column key, value) triples and collect the 'Just' results.-traverseMaybeWithKeys-  :: (Applicative t, Ord r, Ord c)-  => (r -> c -> a -> t (Maybe b))-  -> Table r c a-  -> t (Table r c b)-traverseMaybeWithKeys f (Table (rm, _, _)) = fromMaps <$> rm' <*> cm'-  where-    rm' = Map.traverseWithKey (Map.traverseMaybeWithKey . f) rm-    cm' = transpose' <$> rm'------------------------------------------------------------------------------------ | /O(n)/. Fold the values in the table row by row using the given--- right-associative binary operator.------ > Data.Multimap.Table.foldr (:) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "bcd"-foldr :: (a -> b -> b) -> b -> Table r c a -> b-foldr = foldrWithKeys . const . const---- | /O(n)/. Fold the values in the table row by row using the given--- left-associative binary operator.------ > Data.Multimap.Table.foldl (flip (:)) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "dcb"-foldl :: (a -> b -> a) -> a -> Table r c b -> a-foldl f = foldlWithKeys (\a _ _ -> f a)---- | /O(n)/. Fold the (row key, column key value) triplets in the table---  row by row using the given right-associative binary operator.------ > let f r c a b = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ b in do--- >   foldrWithKeys f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"-foldrWithKeys :: (r -> c -> a -> b -> b) -> b -> Table r c a -> b-foldrWithKeys f b (Table (rm, _, _)) = Map.foldrWithKey f' b rm-  where-    f' = flip . Map.foldrWithKey . f---- | /O(n)/. Fold the (row key, column key, value) triplets in the table---  row by row using the given left-associative binary operator.------ > let f a r c b = show r ++ ":" ++ show c ++ ":" ++ b ++ "|" ++ a in do--- >   foldlWithKeys f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "2:'a':d|1:'b':c|1:'a':b|"-foldlWithKeys :: (a -> r -> c -> b -> a) -> a -> Table r c b -> a-foldlWithKeys f a (Table (rm, _, _)) = Map.foldlWithKey f' a rm-  where-    f' = flip (Map.foldlWithKey . flip f)---- | /O(n)/. A strict version of 'foldr'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > Data.Multimap.Table.foldr' (:) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "bcd"-foldr' :: (a -> b -> b) -> b -> Table r c a -> b-foldr' = foldrWithKeys' . const . const---- | /O(n)/. A strict version of 'foldl'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > Data.Multimap.Table.foldl' (flip (:)) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "dcb"-foldl' :: (a -> b -> a) -> a -> Table r c b -> a-foldl' f = foldlWithKeys' (\a _ _ -> f a)---- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > let f r c a b = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ b in do--- >   foldrWithKeys' f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"-foldrWithKeys' :: (r -> c -> a -> b -> b) -> b -> Table r c a -> b-foldrWithKeys' f b (Table (rm, _, _)) = Map.foldrWithKey' f' b rm-  where-    f' = flip . Map.foldrWithKey' . f---- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the--- operator is evaluated before using the result in the next application.--- This function is strict in the starting value.------ > let f a r c b = show r ++ ":" ++ show c ++ ":" ++ b ++ "|" ++ a in do--- >   foldlWithKeys' f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "2:'a':d|1:'b':c|1:'a':b|"-foldlWithKeys' :: (a -> r -> c -> b -> a) -> a -> Table r c b -> a-foldlWithKeys' f a (Table (rm, _, _)) = Map.foldlWithKey' f' a rm-  where-    f' = flip (Map.foldlWithKey' . flip f)---- | /O(n)/. Fold the (row key, column key, value) triplets in the map--- row by row using the given monoid.------ > let f r c a = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" in do--- >   foldMapWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"-foldMapWithKeys :: Monoid m => (r -> c -> a -> m) -> Table r c a -> m-foldMapWithKeys f (Table (rm, _, _)) = Map.foldMapWithKey f' rm-  where-    f' = Map.foldMapWithKey . f------------------------------------------------------------------------------------ | /O(r)/. Return a mapping from column keys to values for the given--- row key.------ > row 1 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.fromList [('a',"b"),('b',"c")]--- > row 3 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.empty-row :: Ord r => r -> Table r c a -> Map c a-row r (Table (rm, _, _)) = Map.findWithDefault Map.empty r rm---- | /O(c)/. Return a mapping from row keys to values for the given--- column key.------ > column 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.fromList [(1,"b"),(2,"d")]--- > column 'c' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.empty-column :: Ord c => c -> Table r c a -> Map r a-column c (Table (_, cm, _)) = Map.findWithDefault Map.empty c cm---- | Return a mapping from row keys to maps from column keys to values.------ > rowMap (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])--- >   === Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]),(2, Map.fromList [('a',"d")])]-rowMap :: Table r c a -> Map r (Map c a)-rowMap (Table (rm, _, _)) = rm---- | Return a mapping from column keys to maps from row keys to values.------ > columnMap (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])--- >   === Map.fromList [('a', Map.fromList [(1,"b"),(2,"d")]),('b', Map.fromList [(1,"c")])]-columnMap :: Table r c a -> Map c (Map r a)-columnMap (Table (_, cm, _)) = cm---- | Return, in ascending order, the list of all row keys of that have--- at least one value in the table.------ > rowKeys (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [1,2]-rowKeys :: Table r c a -> [r]-rowKeys (Table (rm, _, _)) = Map.keys rm---- | Return, in ascending order, the list of all column keys of that have--- at least one value in the table.------ > columnKeys (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === ['a','b']-columnKeys :: Table r c a -> [c]-columnKeys (Table (_, cm, _)) = Map.keys cm---- | Return the set of all row keys of that have at least one value--- in the table.------ > rowKeysSet (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Set.fromList [1,2]-rowKeysSet :: Table r c a -> Set r-rowKeysSet (Table (rm, _, _)) = Map.keysSet rm---- | Return the set of all column keys of that have at least one value--- in the table.------ > columnKeysSet (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Set.fromList ['a','b']-columnKeysSet :: Table r c a -> Set c-columnKeysSet (Table (_, cm, _)) = Map.keysSet cm---- | Convert the table into a list of (row key, column key, value) triples.------ > toList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-toList :: Table r c a -> [(r, c, a)]-toList (Table (rm, _, _)) = Map.toList (Map.toList <$> rm) >>= distr---- | Convert the table into a list of (row key, column key, value) triples--- in ascending order of row keys, and ascending order of column keys--- with a row.------ > toRowAscList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-toRowAscList :: Table r c a -> [(r, c, a)]-toRowAscList (Table (rm, _, _)) = Map.toAscList (Map.toAscList <$> rm) >>= distr---- | Convert the table into a list of (column key, row key, value) triples--- in ascending order of column keys, and ascending order of row keys--- with a column.------ > toColumnAscList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [('a',1,"b"),('a',2,"d"),('b',1,"c")]-toColumnAscList :: Table r c a -> [(c, r, a)]-toColumnAscList (Table (_, cm, _)) = Map.toAscList (Map.toAscList <$> cm) >>= distr---- | Convert the table into a list of (row key, column key, value) triples--- in descending order of row keys, and descending order of column keys--- with a row.------ > toRowDescList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(2,'a',"d"),(1,'b',"c"),(1,'a',"b")]-toRowDescList :: Table r c a -> [(r, c, a)]-toRowDescList (Table (rm, _, _)) = Map.toDescList (Map.toDescList <$> rm) >>= distr---- | Convert the table into a list of (column key, row key, value) triples--- in descending order of column keys, and descending order of row keys--- with a column.------ > toColumnDescList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [('b',1,"c"),('a',2,"d"),('a',1,"b")]-toColumnDescList :: Table r c a -> [(c, r, a)]-toColumnDescList (Table (_, cm, _)) = Map.toDescList (Map.toDescList <$> cm) >>= distr------------------------------------------------------------------------------------ | /O(n)/, assuming the predicate function takes /O(1)/.--- Retain all values that satisfy the predicate.------ > Data.Multimap.Table.filter (> "c") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"--- > Data.Multimap.Table.filter (> "d") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === empty-filter :: (a -> Bool) -> Table r c a -> Table r c a-filter = filterWithKeys . const . const---- | /O(r)/, assuming the predicate function takes /O(1)/.--- Retain all rows that satisfy the predicate.------ > filterRow even (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"-filterRow :: (r -> Bool) -> Table r c a -> Table r c a-filterRow p (Table (rm, cm, _)) = Table (rm', nonEmpty cm', size' rm')-  where-    rm' = Map.filterWithKey (const . p) rm-    cm' = Map.map (Map.filterWithKey (const . p)) cm---- | /O(c)/, assuming the predicate function takes /O(1)/.--- Retain all columns that satisfy the predicate.------ > filterColumn (> 'a') (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"-filterColumn :: (c -> Bool) -> Table r c a -> Table r c a-filterColumn p (Table (rm, cm, _)) = Table (nonEmpty rm', cm', size' cm')-  where-    rm' = Map.map (Map.filterWithKey (const . p)) rm-    cm' = Map.filterWithKey (const . p) cm---- | /O(c)/, assuming the predicate function takes /O(1)/.--- Retain all (row key, column key, value) triples that satisfy the predicate.------ > filterWithKeys (\r c a -> odd r && c > 'a' && a > "b") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"-filterWithKeys-  :: (r -> c -> a -> Bool)-  -> Table r c a-  -> Table r c a-filterWithKeys p (Table (rm, cm, _)) = fromMaps rm' cm'-  where-    rm' = Map.mapWithKey (Map.filterWithKey . p) rm-    cm' = Map.mapWithKey (Map.filterWithKey . flip p) cm---- | /O(n)/, assuming the function @a -> 'Maybe' b@ takes /O(1)/.--- Map values and collect the 'Just' results.------ > mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])--- >   === fromList [(1,'a',"new a"),(2,'b',"new a")]-mapMaybe :: (a -> Maybe b) -> Table r c a -> Table r c b-mapMaybe = mapMaybeWithKeys . const . const---- | /O(n)/, assuming the function @r -> c -> a -> 'Maybe' b@ takes /O(1)/.--- Map (row key, column key, value) triples and collect the 'Just' results.------ > let f r c a = if r == 1 && a == "c" then Just "new c" else Nothing in do--- >   mapMaybeWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "new c"-mapMaybeWithKeys :: (r -> c -> a -> Maybe b) -> Table r c a -> Table r c b-mapMaybeWithKeys f (Table (rm, cm, _)) = fromMaps rm' cm'-  where-    rm' = Map.mapWithKey (Map.mapMaybeWithKey . f) rm-    cm' = Map.mapWithKey (Map.mapMaybeWithKey . flip f) cm---- | /O(n)/, assuming the function @a -> 'Either' a1 a2@ takes /O(1)/.--- Map values and separate the 'Left' and 'Right' results.------ > mapEither (\a -> if a == "a" then Left a else Right a) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])--- >   === (fromList [(1,'a',"a"),(2,'b',"a")],fromList [(1,'b',"c")])-mapEither :: (a -> Either a1 a2) -> Table r c a -> (Table r c a1, Table r c a2)-mapEither = mapEitherWithKeys . const . const---- | /O(n)/, assuming the function @r -> c -> a -> 'Either' a1 a2@ takes /O(1)/.--- Map (row key, column key, value) triples and separate the 'Left' and 'Right' results.------ > mapEitherWithKeys (\r c a -> if r == 1 && c == 'a' then Left a else Right a) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])--- >   === (fromList [(1,'a',"a")],fromList [(1,'b',"c"),(2,'b',"a")])-mapEitherWithKeys :: (r -> c -> a -> Either a1 a2) -> Table r c a -> (Table r c a1, Table r c a2)-mapEitherWithKeys f (Table (rm, cm, _)) = (fromMaps rm1 cm1, fromMaps rm2 cm2)-  where-    (rm1, rm2) = (fmap fst &&& fmap snd) $ Map.mapWithKey (Map.mapEitherWithKey . f) rm-    (cm1, cm2) = (fmap fst &&& fmap snd) $ Map.mapWithKey (Map.mapEitherWithKey . flip f) cm----------------------------------------------------------------------------------- * Non exported functions---------------------------------------------------------------------------------assoc :: (a, (b, c)) -> (a, b, c)-assoc (a, (b, c)) = (a, b, c)--distr :: (a, [(b, c)]) -> [(a, b, c)]-distr = fmap assoc . uncurry (zip . repeat)---- | Build a table from a row map and a column map.-fromMaps :: Map r (Map c a) -> Map c (Map r a) -> Table r c a-fromMaps rm cm = Table (rm', cm', size' rm')-  where-    rm' = nonEmpty rm-    cm' = nonEmpty cm--fromMaps' :: (Ord r, Ord c) => r -> c -> Map r (Map c a) -> Map c (Map r a) -> Table r c a-fromMaps' r c rm cm = Table (rm', cm', size' rm')-  where-    rm' = nonEmpty' r rm-    cm' = nonEmpty' c cm--nonEmpty :: Map k1 (Map k2 a) -> Map k1 (Map k2 a)-nonEmpty = Map.filter (not . Map.null)--nonEmpty' :: Ord k1 => k1 -> Map k1 (Map k2 a) -> Map k1 (Map k2 a)-nonEmpty' k1 m = case Map.lookup k1 m of-  Just m' | Map.null m' -> Map.delete k1 m-  _ -> m--transpose' :: (Ord r, Ord c) => Map r (Map c a) -> Map c (Map r a)-transpose' = Map.foldrWithKey' f Map.empty-  where-    f r = Map.unionWith Map.union . Map.map (Map.singleton r)--size' :: Map k1 (Map k2 a) -> Int-size' = sum . fmap Map.size--uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d-uncurry3 f ~(a, b, c) = f a b c
+ src/Data/Multimap/Table/Internal.hs view
@@ -0,0 +1,812 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TypeFamilies #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  Data.Multimap.Table.Internal+-- Maintainer  :  Ziyang Liu <free@cofree.io>+--+module Data.Multimap.Table.Internal (+  Table (..)+  , Size++  -- * Construction+  , empty+  , singleton+  , fromRowMap+  , fromColumnMap+  , transpose++  -- ** From Unordered Lists+  , fromList++  -- * Deletion\/Update+  , insert+  , delete+  , deleteRow+  , deleteColumn+  , adjust+  , adjustWithKeys+  , update+  , updateWithKeys+  , alter+  , alterWithKeys++  -- * Query+  -- ** Lookup+  , lookup+  , (!?)+  , (!)+  , hasCell+  , hasRow+  , hasColumn++  -- ** Size+  , null+  , notNull+  , size++  -- * Combine+  -- ** Union+  , union+  , unionWith+  , unionWithKeys+  , unions+  , unionsWith+  , unionsWithKeys++  -- ** Difference+  , difference++  -- * Traversal+  -- ** Map+  , map+  , mapWithKeys+  , traverseWithKeys+  , traverseMaybeWithKeys++  -- ** Folds+  , foldr+  , foldl+  , foldrWithKeys+  , foldlWithKeys+  , foldMapWithKeys++  -- ** Strict Folds+  , foldr'+  , foldl'+  , foldrWithKeys'+  , foldlWithKeys'++  -- * Conversion+  , row+  , column+  , rowMap+  , columnMap+  , rowKeys+  , columnKeys+  , rowKeysSet+  , columnKeysSet++  -- ** Lists+  , toList++  -- ** Ordered lists+  , toRowAscList+  , toColumnAscList+  , toRowDescList+  , toColumnDescList++  -- * Filter+  , filter+  , filterRow+  , filterColumn+  , filterWithKeys++  , mapMaybe+  , mapMaybeWithKeys+  , mapEither+  , mapEitherWithKeys+  ) where++import           Control.Arrow ((&&&))+import           Data.Data (Data)+import qualified Data.Foldable as Foldable+import           Data.Map (Map)+import qualified Data.Map as Map+import qualified Data.Maybe as Maybe+import           Data.Set (Set)++import Prelude hiding (filter, foldl, foldr, lookup, map, null)++infixl 9 !,!?++type Size = Int++newtype Table r c a = Table (Map r (Map c a), Map c (Map r a), Size)+  deriving (Eq, Ord, Data)++instance (Show r, Show c, Show a) => Show (Table r c a) where+  showsPrec d m = showParen (d > 10) $+    showString "fromList " . shows (toList m)++instance (Ord r, Ord c, Read r, Read c, Read a) => Read (Table r c a) where+  readsPrec p = readParen (p > 10) $ \ r -> do+    ("fromList",s) <- lex r+    (xs,t) <- reads s+    pure (fromList xs,t)++instance Functor (Table r c) where+  fmap = map++instance Foldable.Foldable (Table r c) where+  foldMap = foldMapWithKeys . const . const+  {-# INLINE foldMap #-}++instance (Ord r, Ord c) => Traversable (Table r c) where+  traverse = traverseWithKeys . const . const+  {-# INLINE traverse #-}++instance (Ord r, Ord c) => Semigroup (Table r c a) where+  (<>) = union++instance (Ord r, Ord c) => Monoid (Table r c a) where+  mempty = empty+  mappend = (<>)++------------------------------------------------------------------------------++-- | /O(1)/. The empty table.+--+-- > size empty === 0+empty :: Table r c a+empty = Table (Map.empty, Map.empty, 0)++-- | /O(1)/. A table with a single element.+--+-- > singleton 1 'a' "a" === fromList [(1,'a',"a")]+-- > size (singleton 1 'a' "a") === 1+singleton :: r -> c -> a -> Table r c a+singleton r c a = Table (Map.singleton r (Map.singleton c a), Map.singleton c (Map.singleton r a), 1)++-- | Build a table from a list of key\/value pairs.+--+-- > fromList ([] :: [(Int, Char, String)]) === empty+fromList :: (Ord r, Ord c) => [(r, c, a)] -> Table r c a+fromList = Foldable.foldr (uncurry3 insert) empty++-- | Build a table from a row map.+--+-- > fromRowMap (Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]), (2, Map.fromList [('a',"d")])])+-- >   === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+fromRowMap :: (Ord r, Ord c) => Map r (Map c a) -> Table r c a+fromRowMap m = Table (m', transpose' m', size' m')+  where m' = nonEmpty m++-- | Build a table from a column map.+--+-- > fromColumnMap (Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]), (2, Map.fromList [('a',"d")])])+-- >   === fromList [('a',1,"b"),('a',2,"d"),('b',1,"c")]+fromColumnMap :: (Ord r, Ord c) => Map c (Map r a) -> Table r c a+fromColumnMap m = Table (transpose' m', m', size' m')+  where m' = nonEmpty m++-- | Flip the row and column keys.+--+-- > transpose (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [('a',1,"b"),('a',2,"d"),('b',1,"c")]+transpose :: Table r c a -> Table c r a+transpose (Table (rm, cm, sz)) = Table (cm, rm, sz)++------------------------------------------------------------------------------++-- | /O(log k)/. Associate with value with the row key and the column key.+-- If the table already contains a value for those keys, the value is replaced.+--+-- > insert 1 'a' "a" empty === singleton 1 'a' "a"+-- > insert 1 'a' "a" (fromList [(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"d")]+-- > insert 1 'a' "a" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"d")]+insert :: (Ord r, Ord c) => r -> c -> a -> Table r c a -> Table r c a+insert r c a (Table (rm, cm, _)) = fromMaps' r c rm' cm'+  where+    rm' = Map.alter f r rm+    cm' = Map.alter g c cm+    f = Just . maybe (Map.singleton c a) (Map.insert c a)+    g = Just . maybe (Map.singleton r a) (Map.insert r a)++-- | /O(log k)/. Remove the value associated with the given keys.+--+-- > delete 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'b',"c"),(2,'a',"d")]+-- > delete 1 'a' (fromList [(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'b',"c"),(2,'a',"d")]+delete :: (Ord r, Ord c) => r -> c -> Table r c a -> Table r c a+delete r c (Table (rm, cm, _)) = fromMaps' r c rm' cm'+  where+    rm' = Map.adjust (Map.delete c) r rm+    cm' = Map.adjust (Map.delete r) c cm++-- | Remove an entire row.+--+-- > deleteRow 1 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"+-- > deleteRow 3 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+deleteRow :: Ord r => r -> Table r c a -> Table r c a+deleteRow r (Table (rm, cm, _)) = Table (rm', cm', size' rm')+  where+    rm' = Map.delete r rm+    cm' = nonEmpty $ Map.map (Map.delete r) cm++-- | Remove an entire column.+--+-- > deleteColumn 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"+-- > deleteColumn 'z' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+deleteColumn :: Ord c => c -> Table r c a -> Table r c a+deleteColumn c (Table (rm, cm, _)) = Table (rm', cm', size' cm')+  where+    rm' = nonEmpty $ Map.map (Map.delete c) rm+    cm' = Map.delete c cm++-- | /O(log k)/, assuming the function @a -> a@ takes /O(1)/.+-- Update the value at a specific row key and column key, if exists.+--+-- > adjust ("new " ++) 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"new b"),(1,'b',"c"),(2,'a',"d")]+adjust :: (Ord r, Ord c) => (a -> a) -> r -> c -> Table r c a -> Table r c a+adjust = adjustWithKeys . const . const++-- | /O(log k)/, assuming the function @r -> c -> a -> a@ takes /O(1)/.+-- Update the value at a specific row key and column key, if exists.+--+-- > adjustWithKeys (\r c x -> show r ++ ":" ++ show c ++ ":new " ++ x) 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])+-- >   === fromList [(1,'a',"1:'a':new b"),(1,'b',"c"),(2,'a',"d")]+adjustWithKeys+  :: (Ord r, Ord c)+  => (r -> c -> a -> a) -> r -> c -> Table r c a -> Table r c a+adjustWithKeys f = updateWithKeys (\r c a -> Just (f r c a))++-- | /O(log k)/, assuming the function @a -> 'Maybe' a@ takes /O(1)/.+-- The expression (@'update' f r c table@) updates the value at the given+-- row and column keys, if exists. If @f@ returns 'Nothing', the value+-- associated with those keys, if exists is deleted.+--+-- > let f x = if x == "b" then Just "new b" else Nothing in do+-- >   update f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"new b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   update f 1 'a' (fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+update :: (Ord r, Ord c) => (a -> Maybe a) -> r -> c -> Table r c a -> Table r c a+update = updateWithKeys . const . const++-- | /O(log k)/, assuming the function @r -> c -> a -> 'Maybe' a@ takes /O(1)/.+-- The expression (@'updateWithKeys' f r c table@) updates the value at the given+-- row and column keys, if exists. If @f@ returns 'Nothing', the value+-- associated with those keys, if exists is deleted.+--+-- > let f r c x = if x == "b" then Just (show r ++ ":" ++ show c ++ ":new b") else Nothing in do+-- >   updateWithKeys f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"1:'a':new b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   updateWithKeys f 1 'a' (fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+updateWithKeys+  :: (Ord r, Ord c)+  => (r -> c -> a -> Maybe a) -> r -> c -> Table r c a -> Table r c a+updateWithKeys f = alterWithKeys (\r c -> (>>= f r c))++-- | /O(log k)/, assuming the function @'Maybe' a -> 'Maybe' a@ takes /O(1)/.+-- The expression (@'alter' f r c table@) alters the value at the given+-- row and column keys, if exists. It can be used to insert, delete+-- or update a value.+--+-- > let (f,g,h) = (const Nothing, const (Just "hello"), fmap ('z':)) in do+-- >   alter f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   alter f 4 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   alter f 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   alter g 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"hello"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   alter g 4 'e' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c"),(4,'e',"hello")]+-- >   alter h 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"zb"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   alter h 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+alter :: (Ord r, Ord c) => (Maybe a -> Maybe a) -> r -> c -> Table r c a -> Table r c a+alter = alterWithKeys . const . const++-- | /O(log k)/, assuming the function @r -> c -> 'Maybe' a -> 'Maybe' a@ takes /O(1)/.+-- The expression (@'alterWithKeys' f r c table@) alters the value at the given+-- row and column keys, if exists. It can be used to insert, delete+-- or update a value.+--+-- > let (f,g) = (\_ _ _ -> Nothing, \r c -> fmap ((show r ++ ":" ++ show c ++ ":") ++)) in do+-- >   alterWithKeys f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   alterWithKeys f 4 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   alterWithKeys f 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   alterWithKeys g 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"1:'a':b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+-- >   alterWithKeys g 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+alterWithKeys+  :: (Ord r, Ord c)+  => (r -> c -> Maybe a -> Maybe a) -> r -> c -> Table r c a -> Table r c a+alterWithKeys f r c tbl@(Table (rm, cm, _))+  | Just a <- f r c (lookup r c tbl) =+      let rm' = Map.alter (Just . maybe (Map.singleton c a) (Map.insert c a)) r rm+          cm' = Map.alter (Just . maybe (Map.singleton r a) (Map.insert r a)) c cm+       in fromMaps' r c rm' cm'+  | otherwise = delete r c tbl++------------------------------------------------------------------------------++-- | /O(log k)/. Lookup the values at a row key and column key in the map.+lookup :: (Ord r, Ord c) => r -> c -> Table r c a -> Maybe a+lookup r c (Table (rm, _, _)) = Map.lookup r rm >>= Map.lookup c++-- | /O(log k)/. Lookup the values at a row key and column key in the map.+--+-- > fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] !? (1,'a') === Just "b"+-- > fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] !? (1,'c') === Nothing+(!?) :: (Ord r, Ord c) => Table r c a -> (r, c) -> Maybe a+(!?) = flip (uncurry lookup)++-- | /O(log k)/. Lookup the values at a row key and column key in the map.+-- Calls 'error' if the value does not exist.+--+-- > fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] ! (1,'a') === "b"+(!) :: (Ord r, Ord c) => Table r c a -> (r, c) -> a+(!) tbl keys =+  Maybe.fromMaybe (error "Table.!: cell does not exist") (tbl !? keys)++-- | /O(log k)/. Is there a value associated with the given row and+-- column keys?+--+-- > hasCell (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (1,'a') === True+-- > hasCell (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (1,'c') === False+hasCell :: (Ord r, Ord c) => Table r c a -> (r, c) -> Bool+hasCell (Table (rm, _, _)) (r, c) =+  maybe False (Map.member c) (Map.lookup r rm)++-- | /O(log r)/. Is there a row with the given row key that has at least+--  one value?+--+-- > hasRow (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 1 === True+-- > hasRow (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 3 === False+hasRow :: Ord r => Table r c a -> r -> Bool+hasRow (Table (rm, _, _)) r = Map.member r rm++-- | /O(log c)/. Is there a column with the given column key that has at least+-- one value?+--+-- > hasColumn (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 'a' === True+-- > hasColumn (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 'c' === False+hasColumn :: Ord c => Table r c a -> c -> Bool+hasColumn (Table (_, cm, _)) c = Map.member c cm++-- | /O(1)/. Is the table empty?+--+-- > Data.Multimap.Table.null empty === True+-- > Data.Multimap.Table.null (singleton 1 'a' "a") === False+null :: Table r c a -> Bool+null (Table (rm, _, _)) = Map.null rm++-- | /O(1)/. Is the table non-empty?+--+-- > notNull empty === False+-- > notNull (singleton 1 'a' "a") === True+notNull :: Table r c a -> Bool+notNull = not . null++-- | The total number of values for all row and column keys.+--+-- @size@ is evaluated lazily. Forcing the size for the first time takes up to+-- /O(n)/ and subsequent forces take /O(1)/.+--+-- > size empty === 0+-- > size (singleton 1 'a' "a") === 1+-- > size (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === 3+size :: Table r c a -> Int+size (Table (_, _, sz)) = sz++------------------------------------------------------------------------------++-- | Union two tables, preferring values from the first table+-- upon duplicate keys.+--+-- > union (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])+-- >   === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+union :: (Ord r, Ord c) => Table r c a -> Table r c a -> Table r c a+union = unionWith const++-- | Union a number of tables, preferring values from the leftmost table+-- upon duplicate keys.+--+-- > unions [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]+-- >   === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+unions :: (Foldable f, Ord r, Ord c) => f (Table r c a) -> Table r c a+unions = Foldable.foldr union empty++-- | Union two tables with a combining function for duplicate keys.+--+-- > unionWith (++) (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])+-- >   === fromList [(1,'a',"bc"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+unionWith :: (Ord r, Ord c) => (a -> a -> a) -> Table r c a -> Table r c a -> Table r c a+unionWith = unionWithKeys . const . const++-- | Union two tables with a combining function for duplicate keys.+--+-- > let f r c a a' = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ a' in do+-- >   unionWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])+-- >     === fromList [(1,'a',"1:'a':b|c"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+unionWithKeys+  :: (Ord r, Ord c)+  => (r -> c -> a -> a -> a)+  -> Table r c a -> Table r c a -> Table r c a+unionWithKeys f (Table (rm1, cm1, _)) (Table (rm2, cm2, _)) = fromMaps rm cm+  where+    rm = Map.unionWithKey (Map.unionWithKey . f) rm1 rm2+    cm = Map.unionWithKey (Map.unionWithKey . flip f) cm1 cm2++-- | Union a number of tables with a combining function for duplicate keys.+--+-- > unionsWith (++) [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]+-- >   === fromList [(1,'a',"bc"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+unionsWith :: (Foldable f, Ord r, Ord c) => (a -> a -> a) -> f (Table r c a) -> Table r c a+unionsWith f = Foldable.foldr (unionWith f) empty++-- | Union a number of tables with a combining function for duplicate keys.+--+-- > let f r c a a' = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ a' in do+-- >   unionsWithKeys f [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]+-- >     === fromList [(1,'a',"1:'a':b|c"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+unionsWithKeys+  :: (Foldable f, Ord r, Ord c)+  => (r -> c -> a -> a -> a)+  -> f (Table r c a) -> Table r c a+unionsWithKeys f = Foldable.foldr (unionWithKeys f) empty++-- | Difference of two tables. Return values in the first table whose+-- row and column keys do not have an associated value in the second table.+--+-- > difference (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(1,'b',"d"),(2,'b',"b")])+-- >   === singleton 2 'a' "b"+difference :: (Ord r, Ord c) => Table r c a -> Table r c a -> Table r c a+difference (Table (rm1, cm1, _)) (Table (rm2, cm2, _)) = fromMaps rm cm+  where+    rm = Map.differenceWith ((Just .) . Map.difference) rm1 rm2+    cm = Map.differenceWith ((Just .) . Map.difference) cm1 cm2++------------------------------------------------------------------------------++-- | /O(n)/, assuming the function @a -> b@ takes /O(1)/.+-- Map a function over all values in the table.+--+-- > Data.Multimap.Table.map (++ "x") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === fromList [(1,'a',"bx"),(1,'b',"cx"),(2,'a',"bx")]+map :: (a -> b) -> Table r c a -> Table r c b+map = mapWithKeys . const . const++-- | /O(n)/, assuming the function @r -> c -> a -> b@ takes /O(1)/.+-- Map a function over all values in the table.+--+-- > mapWithKeys (\r c x -> show r ++ ":" ++ show c ++ ":" ++ x) (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")])+-- >   === fromList [(1,'a',"1:'a':b"),(1,'b',"1:'b':c"),(2,'a',"2:'a':b")]+mapWithKeys :: (r -> c -> a -> b) -> Table r c a -> Table r c b+mapWithKeys f (Table (rm, cm, sz)) = Table (rm', cm', sz)+  where+    rm' = Map.mapWithKey (Map.mapWithKey . f) rm+    cm' = Map.mapWithKey (Map.mapWithKey . flip f) cm++-- | Traverse the (row key, column key, value) triples and collect the results.+--+-- > let f r c a = if odd r && c > 'a' then Just (a ++ "x") else Nothing in do+-- >   traverseWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === Nothing+-- >   traverseWithKeys f (fromList [(1,'b',"b"),(1,'c',"c"),(3,'d',"b")]) === Just (fromList [(1,'b',"bx"),(1,'c',"cx"),(3,'d',"bx")])+traverseWithKeys+  :: (Applicative t, Ord r, Ord c)+  => (r -> c -> a -> t b)+  -> Table r c a+  -> t (Table r c b)+traverseWithKeys f (Table (rm, _, _)) = fromMaps <$> rm' <*> cm'+  where+    rm' = Map.traverseWithKey (Map.traverseWithKey . f) rm+    cm' = transpose' <$> rm'++-- | Traverse the (row key, column key, value) triples and collect the 'Just' results.+traverseMaybeWithKeys+  :: (Applicative t, Ord r, Ord c)+  => (r -> c -> a -> t (Maybe b))+  -> Table r c a+  -> t (Table r c b)+traverseMaybeWithKeys f (Table (rm, _, _)) = fromMaps <$> rm' <*> cm'+  where+    rm' = Map.traverseWithKey (Map.traverseMaybeWithKey . f) rm+    cm' = transpose' <$> rm'++------------------------------------------------------------------------------++-- | /O(n)/. Fold the values in the table row by row using the given+-- right-associative binary operator.+--+-- > Data.Multimap.Table.foldr (:) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "bcd"+foldr :: (a -> b -> b) -> b -> Table r c a -> b+foldr = foldrWithKeys . const . const++-- | /O(n)/. Fold the values in the table row by row using the given+-- left-associative binary operator.+--+-- > Data.Multimap.Table.foldl (flip (:)) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "dcb"+foldl :: (a -> b -> a) -> a -> Table r c b -> a+foldl f = foldlWithKeys (\a _ _ -> f a)++-- | /O(n)/. Fold the (row key, column key value) triplets in the table+--  row by row using the given right-associative binary operator.+--+-- > let f r c a b = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ b in do+-- >   foldrWithKeys f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"+foldrWithKeys :: (r -> c -> a -> b -> b) -> b -> Table r c a -> b+foldrWithKeys f b (Table (rm, _, _)) = Map.foldrWithKey f' b rm+  where+    f' = flip . Map.foldrWithKey . f++-- | /O(n)/. Fold the (row key, column key, value) triplets in the table+--  row by row using the given left-associative binary operator.+--+-- > let f a r c b = show r ++ ":" ++ show c ++ ":" ++ b ++ "|" ++ a in do+-- >   foldlWithKeys f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "2:'a':d|1:'b':c|1:'a':b|"+foldlWithKeys :: (a -> r -> c -> b -> a) -> a -> Table r c b -> a+foldlWithKeys f a (Table (rm, _, _)) = Map.foldlWithKey f' a rm+  where+    f' = flip (Map.foldlWithKey . flip f)++-- | /O(n)/. A strict version of 'foldr'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > Data.Multimap.Table.foldr' (:) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "bcd"+foldr' :: (a -> b -> b) -> b -> Table r c a -> b+foldr' = foldrWithKeys' . const . const++-- | /O(n)/. A strict version of 'foldl'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > Data.Multimap.Table.foldl' (flip (:)) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "dcb"+foldl' :: (a -> b -> a) -> a -> Table r c b -> a+foldl' f = foldlWithKeys' (\a _ _ -> f a)++-- | /O(n)/. A strict version of 'foldrWithKey'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > let f r c a b = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ b in do+-- >   foldrWithKeys' f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"+foldrWithKeys' :: (r -> c -> a -> b -> b) -> b -> Table r c a -> b+foldrWithKeys' f b (Table (rm, _, _)) = Map.foldrWithKey' f' b rm+  where+    f' = flip . Map.foldrWithKey' . f++-- | /O(n)/. A strict version of 'foldlWithKey'. Each application of the+-- operator is evaluated before using the result in the next application.+-- This function is strict in the starting value.+--+-- > let f a r c b = show r ++ ":" ++ show c ++ ":" ++ b ++ "|" ++ a in do+-- >   foldlWithKeys' f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "2:'a':d|1:'b':c|1:'a':b|"+foldlWithKeys' :: (a -> r -> c -> b -> a) -> a -> Table r c b -> a+foldlWithKeys' f a (Table (rm, _, _)) = Map.foldlWithKey' f' a rm+  where+    f' = flip (Map.foldlWithKey' . flip f)++-- | /O(n)/. Fold the (row key, column key, value) triplets in the map+-- row by row using the given monoid.+--+-- > let f r c a = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" in do+-- >   foldMapWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"+foldMapWithKeys :: Monoid m => (r -> c -> a -> m) -> Table r c a -> m+foldMapWithKeys f (Table (rm, _, _)) = Map.foldMapWithKey f' rm+  where+    f' = Map.foldMapWithKey . f++------------------------------------------------------------------------------++-- | /O(r)/. Return a mapping from column keys to values for the given+-- row key.+--+-- > row 1 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.fromList [('a',"b"),('b',"c")]+-- > row 3 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.empty+row :: Ord r => r -> Table r c a -> Map c a+row r (Table (rm, _, _)) = Map.findWithDefault Map.empty r rm++-- | /O(c)/. Return a mapping from row keys to values for the given+-- column key.+--+-- > column 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.fromList [(1,"b"),(2,"d")]+-- > column 'c' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.empty+column :: Ord c => c -> Table r c a -> Map r a+column c (Table (_, cm, _)) = Map.findWithDefault Map.empty c cm++-- | Return a mapping from row keys to maps from column keys to values.+--+-- > rowMap (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])+-- >   === Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]),(2, Map.fromList [('a',"d")])]+rowMap :: Table r c a -> Map r (Map c a)+rowMap (Table (rm, _, _)) = rm++-- | Return a mapping from column keys to maps from row keys to values.+--+-- > columnMap (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])+-- >   === Map.fromList [('a', Map.fromList [(1,"b"),(2,"d")]),('b', Map.fromList [(1,"c")])]+columnMap :: Table r c a -> Map c (Map r a)+columnMap (Table (_, cm, _)) = cm++-- | Return, in ascending order, the list of all row keys of that have+-- at least one value in the table.+--+-- > rowKeys (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [1,2]+rowKeys :: Table r c a -> [r]+rowKeys (Table (rm, _, _)) = Map.keys rm++-- | Return, in ascending order, the list of all column keys of that have+-- at least one value in the table.+--+-- > columnKeys (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === ['a','b']+columnKeys :: Table r c a -> [c]+columnKeys (Table (_, cm, _)) = Map.keys cm++-- | Return the set of all row keys of that have at least one value+-- in the table.+--+-- > rowKeysSet (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Set.fromList [1,2]+rowKeysSet :: Table r c a -> Set r+rowKeysSet (Table (rm, _, _)) = Map.keysSet rm++-- | Return the set of all column keys of that have at least one value+-- in the table.+--+-- > columnKeysSet (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Set.fromList ['a','b']+columnKeysSet :: Table r c a -> Set c+columnKeysSet (Table (_, cm, _)) = Map.keysSet cm++-- | Convert the table into a list of (row key, column key, value) triples.+--+-- > toList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+toList :: Table r c a -> [(r, c, a)]+toList (Table (rm, _, _)) = Map.toList (Map.toList <$> rm) >>= distr++-- | Convert the table into a list of (row key, column key, value) triples+-- in ascending order of row keys, and ascending order of column keys+-- with a row.+--+-- > toRowAscList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+toRowAscList :: Table r c a -> [(r, c, a)]+toRowAscList (Table (rm, _, _)) = Map.toAscList (Map.toAscList <$> rm) >>= distr++-- | Convert the table into a list of (column key, row key, value) triples+-- in ascending order of column keys, and ascending order of row keys+-- with a column.+--+-- > toColumnAscList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [('a',1,"b"),('a',2,"d"),('b',1,"c")]+toColumnAscList :: Table r c a -> [(c, r, a)]+toColumnAscList (Table (_, cm, _)) = Map.toAscList (Map.toAscList <$> cm) >>= distr++-- | Convert the table into a list of (row key, column key, value) triples+-- in descending order of row keys, and descending order of column keys+-- with a row.+--+-- > toRowDescList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(2,'a',"d"),(1,'b',"c"),(1,'a',"b")]+toRowDescList :: Table r c a -> [(r, c, a)]+toRowDescList (Table (rm, _, _)) = Map.toDescList (Map.toDescList <$> rm) >>= distr++-- | Convert the table into a list of (column key, row key, value) triples+-- in descending order of column keys, and descending order of row keys+-- with a column.+--+-- > toColumnDescList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [('b',1,"c"),('a',2,"d"),('a',1,"b")]+toColumnDescList :: Table r c a -> [(c, r, a)]+toColumnDescList (Table (_, cm, _)) = Map.toDescList (Map.toDescList <$> cm) >>= distr++------------------------------------------------------------------------------++-- | /O(n)/, assuming the predicate function takes /O(1)/.+-- Retain all values that satisfy the predicate.+--+-- > Data.Multimap.Table.filter (> "c") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"+-- > Data.Multimap.Table.filter (> "d") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === empty+filter :: (a -> Bool) -> Table r c a -> Table r c a+filter = filterWithKeys . const . const++-- | /O(r)/, assuming the predicate function takes /O(1)/.+-- Retain all rows that satisfy the predicate.+--+-- > filterRow even (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"+filterRow :: (r -> Bool) -> Table r c a -> Table r c a+filterRow p (Table (rm, cm, _)) = Table (rm', nonEmpty cm', size' rm')+  where+    rm' = Map.filterWithKey (const . p) rm+    cm' = Map.map (Map.filterWithKey (const . p)) cm++-- | /O(c)/, assuming the predicate function takes /O(1)/.+-- Retain all columns that satisfy the predicate.+--+-- > filterColumn (> 'a') (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"+filterColumn :: (c -> Bool) -> Table r c a -> Table r c a+filterColumn p (Table (rm, cm, _)) = Table (nonEmpty rm', cm', size' cm')+  where+    rm' = Map.map (Map.filterWithKey (const . p)) rm+    cm' = Map.filterWithKey (const . p) cm++-- | /O(c)/, assuming the predicate function takes /O(1)/.+-- Retain all (row key, column key, value) triples that satisfy the predicate.+--+-- > filterWithKeys (\r c a -> odd r && c > 'a' && a > "b") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"+filterWithKeys+  :: (r -> c -> a -> Bool)+  -> Table r c a+  -> Table r c a+filterWithKeys p (Table (rm, cm, _)) = fromMaps rm' cm'+  where+    rm' = Map.mapWithKey (Map.filterWithKey . p) rm+    cm' = Map.mapWithKey (Map.filterWithKey . flip p) cm++-- | /O(n)/, assuming the function @a -> 'Maybe' b@ takes /O(1)/.+-- Map values and collect the 'Just' results.+--+-- > mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])+-- >   === fromList [(1,'a',"new a"),(2,'b',"new a")]+mapMaybe :: (a -> Maybe b) -> Table r c a -> Table r c b+mapMaybe = mapMaybeWithKeys . const . const++-- | /O(n)/, assuming the function @r -> c -> a -> 'Maybe' b@ takes /O(1)/.+-- Map (row key, column key, value) triples and collect the 'Just' results.+--+-- > let f r c a = if r == 1 && a == "c" then Just "new c" else Nothing in do+-- >   mapMaybeWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "new c"+mapMaybeWithKeys :: (r -> c -> a -> Maybe b) -> Table r c a -> Table r c b+mapMaybeWithKeys f (Table (rm, cm, _)) = fromMaps rm' cm'+  where+    rm' = Map.mapWithKey (Map.mapMaybeWithKey . f) rm+    cm' = Map.mapWithKey (Map.mapMaybeWithKey . flip f) cm++-- | /O(n)/, assuming the function @a -> 'Either' a1 a2@ takes /O(1)/.+-- Map values and separate the 'Left' and 'Right' results.+--+-- > mapEither (\a -> if a == "a" then Left a else Right a) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])+-- >   === (fromList [(1,'a',"a"),(2,'b',"a")],fromList [(1,'b',"c")])+mapEither :: (a -> Either a1 a2) -> Table r c a -> (Table r c a1, Table r c a2)+mapEither = mapEitherWithKeys . const . const++-- | /O(n)/, assuming the function @r -> c -> a -> 'Either' a1 a2@ takes /O(1)/.+-- Map (row key, column key, value) triples and separate the 'Left' and 'Right' results.+--+-- > mapEitherWithKeys (\r c a -> if r == 1 && c == 'a' then Left a else Right a) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])+-- >   === (fromList [(1,'a',"a")],fromList [(1,'b',"c"),(2,'b',"a")])+mapEitherWithKeys :: (r -> c -> a -> Either a1 a2) -> Table r c a -> (Table r c a1, Table r c a2)+mapEitherWithKeys f (Table (rm, cm, _)) = (fromMaps rm1 cm1, fromMaps rm2 cm2)+  where+    (rm1, rm2) = (fmap fst &&& fmap snd) $ Map.mapWithKey (Map.mapEitherWithKey . f) rm+    (cm1, cm2) = (fmap fst &&& fmap snd) $ Map.mapWithKey (Map.mapEitherWithKey . flip f) cm++------------------------------------------------------------------------------+-- * Non exported functions+------------------------------------------------------------------------------++assoc :: (a, (b, c)) -> (a, b, c)+assoc (a, (b, c)) = (a, b, c)++distr :: (a, [(b, c)]) -> [(a, b, c)]+distr = fmap assoc . uncurry (zip . repeat)++-- | Build a table from a row map and a column map.+fromMaps :: Map r (Map c a) -> Map c (Map r a) -> Table r c a+fromMaps rm cm = Table (rm', cm', size' rm')+  where+    rm' = nonEmpty rm+    cm' = nonEmpty cm++fromMaps' :: (Ord r, Ord c) => r -> c -> Map r (Map c a) -> Map c (Map r a) -> Table r c a+fromMaps' r c rm cm = Table (rm', cm', size' rm')+  where+    rm' = nonEmpty' r rm+    cm' = nonEmpty' c cm++nonEmpty :: Map k1 (Map k2 a) -> Map k1 (Map k2 a)+nonEmpty = Map.filter (not . Map.null)++nonEmpty' :: Ord k1 => k1 -> Map k1 (Map k2 a) -> Map k1 (Map k2 a)+nonEmpty' k1 m = case Map.lookup k1 m of+  Just m' | Map.null m' -> Map.delete k1 m+  _ -> m++transpose' :: (Ord r, Ord c) => Map r (Map c a) -> Map c (Map r a)+transpose' = Map.foldrWithKey' f Map.empty+  where+    f r = Map.unionWith Map.union . Map.map (Map.singleton r)++size' :: Map k1 (Map k2 a) -> Int+size' = sum . fmap Map.size++uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d+uncurry3 f ~(a, b, c) = f a b c
+ test/hspec/Data/Multimap/ConversionsSpec.hs view
@@ -0,0 +1,23 @@+-- Generated code, do not modify by hand. Generate by running TestGen.hs.++{-# OPTIONS_GHC -w #-}+module Data.Multimap.ConversionsSpec where++import Test.Hspec+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.Multimap.Conversions as Data.Multimap.Conversions+import qualified Data.Multimap.Internal as Data.Multimap+import qualified Data.Multimap.Set.Internal as Data.Multimap.Set++(===) :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation+(===) = shouldBe++spec :: Spec+spec = do+  describe "Testing Data.Multimap.Conversions" $ do+    it "" $ do+      toMultimapAsc (Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.fromList [(1,'a'),(1,'b'),(2,'c')]+      toMultimapDesc (Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.fromList [(1,'b'),(1,'a'),(2,'c')]+      toSetMultimap (Data.Multimap.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]
+ test/hspec/Data/Multimap/InternalSpec.hs view
@@ -0,0 +1,141 @@+-- Generated code, do not modify by hand. Generate by running TestGen.hs.++{-# OPTIONS_GHC -w #-}+module Data.Multimap.InternalSpec where++import Test.Hspec+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.Multimap.Internal as Data.Multimap++(===) :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation+(===) = shouldBe++spec :: Spec+spec = do+  describe "Testing Data.Multimap.Internal" $ do+    it "" $ do+      size empty === 0+      singleton 1 'a' === fromList [(1, 'a')]+      size (singleton 1 'a') === 1+      fromList ([] :: [(Int, Char)]) === empty+      fromMap' (Map.fromList [(1, "ab"), (2, ""), (3, "c")]) === fromList [(1, 'a'), (1, 'b'), (3, 'c')]+      insert 1 'a' empty === singleton 1 'a'+      insert 1 'a' (fromList [(2, 'b'), (2, 'c')]) === fromList [(1, 'a'), (2, 'b'), (2, 'c')]+      insert 1 'a' (fromList [(1, 'b'), (2, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]+      delete 1 (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === singleton 2 'c'+      deleteWithValue 1 'c' (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]+      deleteWithValue 1 'c' (fromList [(1, 'a'), (1, 'b'), (2, 'c'), (1, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]+      deleteWithValue 1 'c' (fromList [(2, 'c'), (1, 'c')]) === singleton 2 'c'+      deleteOne 1 (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === fromList [(1, 'b'), (2, 'c')]+      deleteOne 1 (fromList [(2, 'c'), (1, 'c')]) === singleton 2 'c'+      adjust ("new " ++) 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(1,"new b"),(2,"c")]+      adjustWithKey (\k x -> show k ++ ":new " ++ x) 1 (fromList [(1,"a"),(1,"b"),(2,"c")])+        === fromList [(1,"1:new a"),(1,"1:new b"),(2,"c")]+      let f x = if x == "a" then Just "new a" else Nothing in do+        update f 1 (fromList [(1,"a"),(1, "b"),(2,"c")]) === fromList [(1,"new a"),(2, "c")]+        update f 1 (fromList [(1,"b"),(1, "b"),(2,"c")]) === singleton 2 "c"+      update' NonEmpty.tail 1 (fromList [(1, "a"), (1, "b"), (2, "c")]) === fromList [(1, "b"), (2, "c")]+      update' NonEmpty.tail 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"+      let f k x = if x == "a" then Just (show k ++ ":new a") else Nothing in do+        updateWithKey f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"1:new a"),(2,"c")]+        updateWithKey f 1 (fromList [(1,"b"),(1,"b"),(2,"c")]) === singleton 2 "c"+      let f k xs = if NonEmpty.length xs == 1 then (show k : NonEmpty.toList xs) else [] in do+        updateWithKey' f 1 (fromList [(1, "a"), (1, "b"), (2, "c")]) === singleton 2 "c"+        updateWithKey' f 1 (fromList [(1, "a"), (2, "b"), (2, "c")]) === fromList [(1, "1"), (1, "a"), (2, "b"), (2, "c")]+      let (f, g) = (const [], ('c':)) in do+        alter f 1 (fromList [(1, 'a'), (2, 'b')]) === singleton 2 'b'+        alter f 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b')]+        alter g 1 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'c'), (1, 'a'), (2, 'b')]+        alter g 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b'), (3, 'c')]+      let (f, g) = (const (const []), (:) . show) in do+        alterWithKey f 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"+        alterWithKey f 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b")]+        alterWithKey g 1 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "1"), (1, "a"), (2, "b")]+        alterWithKey g 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b"), (3, "3")]+      fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 3 === "ac"+      fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 2 === []+      member 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === True+      member 1 (deleteOne 1 (fromList [(2, 'c'), (1, 'c')])) === False+      notMember 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === False+      notMember 1 (deleteOne 1 (fromList [(2, 'c'), (1, 'c')])) === True+      Data.Multimap.null empty === True+      Data.Multimap.null (singleton 1 'a') === False+      notNull empty === False+      notNull (singleton 1 'a') === True+      size empty === 0+      size (singleton 1 'a') === 1+      size (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === 3+      union (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b')])+        === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c'),(2,'b')]+      unions [fromList [(1,'a'),(2,'b'),(2,'c')], fromList [(1,'d'),(2,'b')]]+        === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c'),(2,'b')]+      difference (fromList [(1,'a'),(2,'b'),(2,'c'),(2,'b')]) (fromList [(1,'d'),(2,'b'),(2,'a')])+        === fromList [(1,'a'), (2,'c'), (2,'b')]+      Data.Multimap.map (++ "x") (fromList [(1,"a"),(1,"a"),(2,"b")]) === fromList [(1,"ax"),(1,"ax"),(2,"bx")]+      mapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1,"a"),(1,"a"),(2,"b")]) === fromList [(1,"1:a"),(1,"1:a"),(2,"2:b")]+      let f k a = if odd k then Just (succ a) else Nothing in do+        traverseWithKey f (fromList [(1, 'a'), (1, 'b'), (3, 'b'), (3, 'c')]) === Just (fromList [(1, 'b'), (1, 'c'), (3, 'c'), (3, 'd')])+        traverseWithKey f (fromList [(1, 'a'), (1, 'b'), (2, 'b')]) === Nothing+      Data.Multimap.foldr ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+      Data.Multimap.foldl (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+      foldrWithKey (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+      foldlWithKey (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+      Data.Multimap.foldr' ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+      Data.Multimap.foldl' (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+      foldrWithKey' (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+      foldlWithKey' (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+      foldMapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1, "a"), (1, "a"), (2, "b")]) === "1:a1:a2:b"+      elems (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === "bbac"+      elems (empty :: Multimap Int Char) === []+      keys (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === [1,2,3]+      keys (empty :: Multimap Int Char) === []+      keysSet (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === Set.fromList [1,2,3]+      keysSet (empty :: Multimap Int Char) === Set.empty+      assocs (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]+      toList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]+      toAscList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]+      toDescList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(3,'c'),(2,'a'),(1,'b'),(1,'a')]+      toAscListBF (fromList [("Foo",1),("Foo",2),("Foo",3),("Bar",4),("Bar",5),("Baz",6)])+        === [("Bar",4),("Baz",6),("Foo",1),("Bar",5),("Foo",2),("Foo",3)]+      toDescListBF (fromList [("Foo",1),("Foo",2),("Foo",3),("Bar",4),("Bar",5),("Baz",6)])+        === [("Foo",1),("Baz",6),("Bar",4),("Foo",2),("Bar",5),("Foo",3)]+      Data.Multimap.filter (> 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 1 'b'+      Data.Multimap.filter (< 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === empty+      filterKey even (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 2 'a'+      filterWithKey (\k a -> even k && a > 'a') (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'b')]) === singleton 2 'b'+      let f a | a > 'b' = Just True+              | a < 'b' = Just False+              | a == 'b' = Nothing+       in do+         filterM f (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'c')]) === Nothing+         filterM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Just (fromList [(1,'c'),(2,'c')])+      let f k a | even k && a > 'b' = Just True+                | odd k && a < 'b' = Just False+                | otherwise = Nothing+       in do+         filterWithKeyM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Nothing+         filterWithKeyM f (fromList [(1,'a'),(1,'a'),(2,'c'),(2,'c')]) === Just (fromList [(2,'c'),(2,'c')])+      mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])+        === fromList [(1,"new a"),(2,"new a")]+      mapMaybeWithKey (\k a -> if k > 1 && a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])+        === singleton 2 "new a"+      mapEither (\a -> if a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])+        === (fromList [(1,'a'),(2,'a')],fromList [(1,'c'),(2,'c')])+      mapEitherWithKey (\k a -> if even k && a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])+        === (fromList [(2,'a')],fromList [(1,'a'),(1,'c'),(2,'c')])+      lookupMin (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (1, NonEmpty.fromList "ac")+      lookupMin (empty :: Multimap Int Char) === Nothing+      lookupMax (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (2, NonEmpty.fromList "c")+      lookupMax (empty :: Multimap Int Char) === Nothing+      lookupLT 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+      lookupLT 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")+      lookupGT 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+      lookupGT 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")+      lookupLE 0 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+      lookupLE 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (1, NonEmpty.fromList "a")+      lookupLE 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")+      lookupGE 6 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+      lookupGE 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (5, NonEmpty.fromList "c")+      lookupGE 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")
+ test/hspec/Data/Multimap/Set/InternalSpec.hs view
@@ -0,0 +1,131 @@+-- Generated code, do not modify by hand. Generate by running TestGen.hs.++{-# OPTIONS_GHC -w #-}+module Data.Multimap.Set.InternalSpec where++import Test.Hspec+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.Multimap.Set.Internal as Data.Multimap.Set++(===) :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation+(===) = shouldBe++spec :: Spec+spec = do+  describe "Testing Data.Multimap.Set.Internal" $ do+    it "" $ do+      size empty === 0+      singleton 1 'a' === fromList [(1, 'a')]+      size (singleton 1 'a') === 1+      fromList ([] :: [(Int, Char)]) === empty+      fromList [(1, 'b'), (2, 'a'), (1, 'b')] === fromList [(1, 'b'), (2, 'a')]+      insert 1 'a' empty === singleton 1 'a'+      insert 1 'a' (fromList [(1, 'b'), (2, 'a')]) === fromList [(1, 'a'), (1, 'b'), (2, 'a')]+      insert 1 'a' (fromList [(1, 'a'), (2, 'c')]) === fromList [(1, 'a'), (2, 'c')]+      delete 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === singleton 2 'c'+      deleteWithValue 1 'c' (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]+      deleteWithValue 1 'c' (fromList [(2,'c'),(1,'c')]) === singleton 2 'c'+      deleteMax 3 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]+      deleteMax 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(2,'c')]+      deleteMin 3 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]+      deleteMin 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'b'),(2,'c')]+      adjust ("new " ++) 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(1,"new b"),(2,"c")]+      adjust (const "z") 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"z"),(2,"c")]+      adjustWithKey (\k x -> show k ++ ":new " ++ x) 1 (fromList [(1,"a"),(1,"b"),(2,"c")])+        === fromList [(1,"1:new a"),(1,"1:new b"),(2,"c")]+      let f x = if x == "a" then Just "new a" else Nothing in do+        update f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(2, "c")]+        update f 1 (fromList [(1,"b"),(1,"c"),(2,"c")]) === singleton 2 "c"+      let f k x = if x == "a" then Just (show k ++ ":new a") else Nothing in do+        updateWithKey f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"1:new a"),(2,"c")]+        updateWithKey f 1 (fromList [(1,"b"),(1,"c"),(2,"c")]) === singleton 2 "c"+      let (f, g) = (const Set.empty, Set.insert 'c') in do+        alter f 1 (fromList [(1, 'a'), (2, 'b')]) === singleton 2 'b'+        alter f 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b')]+        alter g 1 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'c'), (1, 'a'), (2, 'b')]+        alter g 1 (fromList [(1, 'c'), (2, 'b')]) === fromList [(1, 'c'), (2, 'b')]+        alter g 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b'), (3, 'c')]+      let (f, g) = (const (const Set.empty), Set.insert . show) in do+        alterWithKey f 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"+        alterWithKey f 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b")]+        alterWithKey g 1 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "1"), (1, "a"), (2, "b")]+        alterWithKey g 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b"), (3, "3")]+      fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 3 === Set.fromList "ac"+      fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 2 === Set.empty+      member 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === True+      member 1 (deleteMax 1 (fromList [(2, 'c'), (1, 'c')])) === False+      notMember 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === False+      notMember 1 (deleteMin 1 (fromList [(2, 'c'), (1, 'c')])) === True+      Data.Multimap.Set.null empty === True+      Data.Multimap.Set.null (singleton 1 'a') === False+      notNull empty === False+      notNull (singleton 1 'a') === True+      size empty === 0+      size (singleton 1 'a') === 1+      size (fromList [(1, 'a'), (2, 'b'), (2, 'c'), (2, 'b')]) === 3+      union (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b')])+        === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c')]+      unions [fromList [(1,'a'),(2,'b'),(2,'c')], fromList [(1,'d'),(2,'b')]]+        === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c')]+      difference (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b'),(2,'a')])+        === fromList [(1,'a'),(2,'c')]+      Data.Multimap.Set.map (++ "x") (fromList [(1,"a"),(2,"b")]) === fromList [(1,"ax"),(2,"bx")]+      Data.Multimap.Set.map (const "c") (fromList [(1,"a"),(1,"b"),(2,"b")]) === fromList [(1,"c"),(2,"c")]+      mapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1,"a"),(2,"b")]) === fromList [(1,"1:a"),(2,"2:b")]+      Data.Multimap.Set.foldr ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+      Data.Multimap.Set.foldl (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+      foldrWithKey (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+      foldlWithKey (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+      Data.Multimap.Set.foldr' ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+      Data.Multimap.Set.foldl' (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11+      foldrWithKey' (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+      foldlWithKey' (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15+      foldMapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1, "a"), (1, "c"), (2, "b")]) === "1:a1:c2:b"+      elems (fromList [(2,'a'),(1,'b'),(3,'d'),(3,'c'),(1,'b')]) === "bacd"+      elems (empty :: SetMultimap Int Char) === []+      keys (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'b')]) === [1,2,3]+      keys (empty :: SetMultimap Int Char) === []+      keysSet (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'b')]) === Set.fromList [1,2,3]+      keysSet (empty :: SetMultimap Int Char) === Set.empty+      toList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'a'),(1,'b'),(2,'a'),(3,'c')]+      toAscList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'a'),(1,'b'),(2,'a'),(3,'c')]+      toDescList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(3,'c'),(2,'a'),(1,'b'),(1,'a')]+      Data.Multimap.Set.filter (> 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 1 'b'+      Data.Multimap.Set.filter (< 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === empty+      filterWithKey (\k a -> even k && a > 'a') (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'b')]) === singleton 2 'b'+      let f a | a > 'b' = Just True+              | a < 'b' = Just False+              | a == 'b' = Nothing+       in do+         filterM f (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'c')]) === Nothing+         filterM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Just (fromList [(1,'c'),(2,'c')])+      let f k a | even k && a > 'b' = Just True+                | odd k && a < 'b' = Just False+                | otherwise = Nothing+       in do+         filterWithKeyM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Nothing+         filterWithKeyM f (fromList [(1,'a'),(3,'a'),(2,'c'),(4,'c')]) === Just (fromList [(2,'c'),(4,'c')])+      mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])+        === fromList [(1,"new a"),(2,"new a")]+      mapMaybeWithKey (\k a -> if k > 1 && a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])+        === singleton 2 "new a"+      mapEither (\a -> if a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])+        === (fromList [(1,'a'),(2,'a')],fromList [(1,'c'),(2,'c')])+      mapEitherWithKey (\k a -> if even k && a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])+        === (fromList [(2,'a')],fromList [(1,'a'),(1,'c'),(2,'c')])+      lookupMin (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (1, Set.fromList "ac")+      lookupMin (empty :: SetMultimap Int Char) === Nothing+      lookupMax (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (2, Set.fromList "c")+      lookupMax (empty :: SetMultimap Int Char) === Nothing+      lookupLT 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+      lookupLT 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")+      lookupGT 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+      lookupGT 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")+      lookupLE 0 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+      lookupLE 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (1, Set.fromList "a")+      lookupLE 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")+      lookupGE 6 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing+      lookupGE 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (5, Set.fromList "c")+      lookupGE 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")
test/hspec/Data/Multimap/SetSpec.hs view
@@ -1,4 +1,4 @@--- Generated code, do not modify by hand. Generate by running "stack build && stack exec test-gen".+-- Generated code, do not modify by hand. Generate by running TestGen.hs.  {-# OPTIONS_GHC -w #-} module Data.Multimap.SetSpec where@@ -7,7 +7,8 @@ import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Map as Map import qualified Data.Set as Set-import Data.Multimap.Set+import Data.Multimap.Set as Data.Multimap.Set+import qualified Data.Multimap as Data.Multimap  (===) :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation (===) = shouldBe@@ -16,116 +17,4 @@ spec = do   describe "Testing Data.Multimap.Set" $ do     it "" $ do-      size empty === 0-      singleton 1 'a' === fromList [(1, 'a')]-      size (singleton 1 'a') === 1-      fromList ([] :: [(Int, Char)]) === empty-      fromList [(1, 'b'), (2, 'a'), (1, 'b')] === fromList [(1, 'b'), (2, 'a')]-      insert 1 'a' empty === singleton 1 'a'-      insert 1 'a' (fromList [(1, 'b'), (2, 'a')]) === fromList [(1, 'a'), (1, 'b'), (2, 'a')]-      insert 1 'a' (fromList [(1, 'a'), (2, 'c')]) === fromList [(1, 'a'), (2, 'c')]-      delete 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === singleton 2 'c'-      deleteWithValue 1 'c' (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]-      deleteWithValue 1 'c' (fromList [(2,'c'),(1,'c')]) === singleton 2 'c'-      deleteMax 3 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]-      deleteMax 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(2,'c')]-      deleteMin 3 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'a'),(1,'b'),(2,'c')]-      deleteMin 1 (fromList [(1,'a'),(1,'b'),(2,'c')]) === fromList [(1,'b'),(2,'c')]-      adjust ("new " ++) 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(1,"new b"),(2,"c")]-      adjust (const "z") 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"z"),(2,"c")]-      adjustWithKey (\k x -> show k ++ ":new " ++ x) 1 (fromList [(1,"a"),(1,"b"),(2,"c")])-        === fromList [(1,"1:new a"),(1,"1:new b"),(2,"c")]-      let f x = if x == "a" then Just "new a" else Nothing in do-        update f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(2, "c")]-        update f 1 (fromList [(1,"b"),(1,"c"),(2,"c")]) === singleton 2 "c"-      let f k x = if x == "a" then Just (show k ++ ":new a") else Nothing in do-        updateWithKey f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"1:new a"),(2,"c")]-        updateWithKey f 1 (fromList [(1,"b"),(1,"c"),(2,"c")]) === singleton 2 "c"-      let (f, g) = (const Set.empty, Set.insert 'c') in do-        alter f 1 (fromList [(1, 'a'), (2, 'b')]) === singleton 2 'b'-        alter f 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b')]-        alter g 1 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'c'), (1, 'a'), (2, 'b')]-        alter g 1 (fromList [(1, 'c'), (2, 'b')]) === fromList [(1, 'c'), (2, 'b')]-        alter g 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b'), (3, 'c')]-      let (f, g) = (const (const Set.empty), Set.insert . show) in do-        alterWithKey f 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"-        alterWithKey f 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b")]-        alterWithKey g 1 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "1"), (1, "a"), (2, "b")]-        alterWithKey g 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b"), (3, "3")]-      fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 3 === Set.fromList "ac"-      fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 2 === Set.empty-      member 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === True-      member 1 (deleteMax 1 (fromList [(2, 'c'), (1, 'c')])) === False-      notMember 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === False-      notMember 1 (deleteMin 1 (fromList [(2, 'c'), (1, 'c')])) === True-      Data.Multimap.Set.null empty === True-      Data.Multimap.Set.null (singleton 1 'a') === False-      notNull empty === False-      notNull (singleton 1 'a') === True-      size empty === 0-      size (singleton 1 'a') === 1-      size (fromList [(1, 'a'), (2, 'b'), (2, 'c'), (2, 'b')]) === 3-      union (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b')])-        === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c')]-      unions [fromList [(1,'a'),(2,'b'),(2,'c')], fromList [(1,'d'),(2,'b')]]-        === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c')]-      difference (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b'),(2,'a')])-        === fromList [(1,'a'),(2,'c')]-      Data.Multimap.Set.map (++ "x") (fromList [(1,"a"),(2,"b")]) === fromList [(1,"ax"),(2,"bx")]-      Data.Multimap.Set.map (const "c") (fromList [(1,"a"),(1,"b"),(2,"b")]) === fromList [(1,"c"),(2,"c")]-      mapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1,"a"),(2,"b")]) === fromList [(1,"1:a"),(2,"2:b")]-      Data.Multimap.Set.foldr ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-      Data.Multimap.Set.foldl (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-      foldrWithKey (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-      foldlWithKey (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-      Data.Multimap.Set.foldr' ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-      Data.Multimap.Set.foldl' (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-      foldrWithKey' (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-      foldlWithKey' (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-      foldMapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1, "a"), (1, "c"), (2, "b")]) === "1:a1:c2:b"-      elems (fromList [(2,'a'),(1,'b'),(3,'d'),(3,'c'),(1,'b')]) === "bacd"-      elems (empty :: SetMultimap Int Char) === []-      keys (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'b')]) === [1,2,3]-      keys (empty :: SetMultimap Int Char) === []-      keysSet (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'b')]) === Set.fromList [1,2,3]-      keysSet (empty :: SetMultimap Int Char) === Set.empty-      toList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'a'),(1,'b'),(2,'a'),(3,'c')]-      toAscList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'a'),(1,'b'),(2,'a'),(3,'c')]-      toDescList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(3,'c'),(2,'a'),(1,'b'),(1,'a')]-      Data.Multimap.Set.filter (> 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 1 'b'-      Data.Multimap.Set.filter (< 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === empty-      filterWithKey (\k a -> even k && a > 'a') (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'b')]) === singleton 2 'b'-      let f a | a > 'b' = Just True-              | a < 'b' = Just False-              | a == 'b' = Nothing-       in do-         filterM f (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'c')]) === Nothing-         filterM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Just (fromList [(1,'c'),(2,'c')])-      let f k a | even k && a > 'b' = Just True-                | odd k && a < 'b' = Just False-                | otherwise = Nothing-       in do-         filterWithKeyM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Nothing-         filterWithKeyM f (fromList [(1,'a'),(3,'a'),(2,'c'),(4,'c')]) === Just (fromList [(2,'c'),(4,'c')])-      mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])-        === fromList [(1,"new a"),(2,"new a")]-      mapMaybeWithKey (\k a -> if k > 1 && a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])-        === singleton 2 "new a"-      mapEither (\a -> if a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])-        === (fromList [(1,'a'),(2,'a')],fromList [(1,'c'),(2,'c')])-      mapEitherWithKey (\k a -> if even k && a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])-        === (fromList [(2,'a')],fromList [(1,'a'),(1,'c'),(2,'c')])-      lookupMin (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (1, Set.fromList "ac")-      lookupMin (empty :: SetMultimap Int Char) === Nothing-      lookupMax (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (2, Set.fromList "c")-      lookupMax (empty :: SetMultimap Int Char) === Nothing-      lookupLT 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing-      lookupLT 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")-      lookupGT 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing-      lookupGT 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")-      lookupLE 0 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing-      lookupLE 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (1, Set.fromList "a")-      lookupLE 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")-      lookupGE 6 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing-      lookupGE 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (5, Set.fromList "c")-      lookupGE 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, Set.fromList "bc")+      fromMultimap (Data.Multimap.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]
+ test/hspec/Data/Multimap/Table/InternalSpec.hs view
@@ -0,0 +1,141 @@+-- Generated code, do not modify by hand. Generate by running TestGen.hs.++{-# OPTIONS_GHC -w #-}+module Data.Multimap.Table.InternalSpec where++import Test.Hspec+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.Multimap.Table.Internal as Data.Multimap.Table++(===) :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation+(===) = shouldBe++spec :: Spec+spec = do+  describe "Testing Data.Multimap.Table.Internal" $ do+    it "" $ do+      size empty === 0+      singleton 1 'a' "a" === fromList [(1,'a',"a")]+      size (singleton 1 'a' "a") === 1+      fromList ([] :: [(Int, Char, String)]) === empty+      fromRowMap (Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]), (2, Map.fromList [('a',"d")])])+        === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+      fromColumnMap (Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]), (2, Map.fromList [('a',"d")])])+        === fromList [('a',1,"b"),('a',2,"d"),('b',1,"c")]+      transpose (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [('a',1,"b"),('a',2,"d"),('b',1,"c")]+      insert 1 'a' "a" empty === singleton 1 'a' "a"+      insert 1 'a' "a" (fromList [(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"d")]+      insert 1 'a' "a" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"d")]+      delete 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'b',"c"),(2,'a',"d")]+      delete 1 'a' (fromList [(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'b',"c"),(2,'a',"d")]+      deleteRow 1 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"+      deleteRow 3 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+      deleteColumn 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"+      deleteColumn 'z' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+      adjust ("new " ++) 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"new b"),(1,'b',"c"),(2,'a',"d")]+      adjustWithKeys (\r c x -> show r ++ ":" ++ show c ++ ":new " ++ x) 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])+        === fromList [(1,'a',"1:'a':new b"),(1,'b',"c"),(2,'a',"d")]+      let f x = if x == "b" then Just "new b" else Nothing in do+        update f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"new b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        update f 1 'a' (fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+      let f r c x = if x == "b" then Just (show r ++ ":" ++ show c ++ ":new b") else Nothing in do+        updateWithKeys f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"1:'a':new b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        updateWithKeys f 1 'a' (fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+      let (f,g,h) = (const Nothing, const (Just "hello"), fmap ('z':)) in do+        alter f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        alter f 4 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        alter f 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        alter g 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"hello"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        alter g 4 'e' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c"),(4,'e',"hello")]+        alter h 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"zb"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        alter h 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+      let (f,g) = (\_ _ _ -> Nothing, \r c -> fmap ((show r ++ ":" ++ show c ++ ":") ++)) in do+        alterWithKeys f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        alterWithKeys f 4 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        alterWithKeys f 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        alterWithKeys g 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"1:'a':b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+        alterWithKeys g 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]+      fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] !? (1,'a') === Just "b"+      fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] !? (1,'c') === Nothing+      fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] ! (1,'a') === "b"+      hasCell (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (1,'a') === True+      hasCell (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (1,'c') === False+      hasRow (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 1 === True+      hasRow (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 3 === False+      hasColumn (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 'a' === True+      hasColumn (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 'c' === False+      Data.Multimap.Table.null empty === True+      Data.Multimap.Table.null (singleton 1 'a' "a") === False+      notNull empty === False+      notNull (singleton 1 'a' "a") === True+      size empty === 0+      size (singleton 1 'a' "a") === 1+      size (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === 3+      union (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])+        === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+      unions [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]+        === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+      unionWith (++) (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])+        === fromList [(1,'a',"bc"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+      let f r c a a' = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ a' in do+        unionWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])+          === fromList [(1,'a',"1:'a':b|c"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+      unionsWith (++) [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]+        === fromList [(1,'a',"bc"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+      let f r c a a' = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ a' in do+        unionsWithKeys f [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]+          === fromList [(1,'a',"1:'a':b|c"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]+      difference (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(1,'b',"d"),(2,'b',"b")])+        === singleton 2 'a' "b"+      Data.Multimap.Table.map (++ "x") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === fromList [(1,'a',"bx"),(1,'b',"cx"),(2,'a',"bx")]+      mapWithKeys (\r c x -> show r ++ ":" ++ show c ++ ":" ++ x) (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")])+        === fromList [(1,'a',"1:'a':b"),(1,'b',"1:'b':c"),(2,'a',"2:'a':b")]+      let f r c a = if odd r && c > 'a' then Just (a ++ "x") else Nothing in do+        traverseWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === Nothing+        traverseWithKeys f (fromList [(1,'b',"b"),(1,'c',"c"),(3,'d',"b")]) === Just (fromList [(1,'b',"bx"),(1,'c',"cx"),(3,'d',"bx")])+      Data.Multimap.Table.foldr (:) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "bcd"+      Data.Multimap.Table.foldl (flip (:)) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "dcb"+      let f r c a b = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ b in do+        foldrWithKeys f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"+      let f a r c b = show r ++ ":" ++ show c ++ ":" ++ b ++ "|" ++ a in do+        foldlWithKeys f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "2:'a':d|1:'b':c|1:'a':b|"+      Data.Multimap.Table.foldr' (:) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "bcd"+      Data.Multimap.Table.foldl' (flip (:)) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "dcb"+      let f r c a b = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ b in do+        foldrWithKeys' f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"+      let f a r c b = show r ++ ":" ++ show c ++ ":" ++ b ++ "|" ++ a in do+        foldlWithKeys' f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "2:'a':d|1:'b':c|1:'a':b|"+      let f r c a = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" in do+        foldMapWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"+      row 1 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.fromList [('a',"b"),('b',"c")]+      row 3 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.empty+      column 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.fromList [(1,"b"),(2,"d")]+      column 'c' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.empty+      rowMap (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])+        === Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]),(2, Map.fromList [('a',"d")])]+      columnMap (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])+        === Map.fromList [('a', Map.fromList [(1,"b"),(2,"d")]),('b', Map.fromList [(1,"c")])]+      rowKeys (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [1,2]+      columnKeys (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === ['a','b']+      rowKeysSet (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Set.fromList [1,2]+      columnKeysSet (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Set.fromList ['a','b']+      toList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+      toRowAscList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]+      toColumnAscList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [('a',1,"b"),('a',2,"d"),('b',1,"c")]+      toRowDescList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(2,'a',"d"),(1,'b',"c"),(1,'a',"b")]+      toColumnDescList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [('b',1,"c"),('a',2,"d"),('a',1,"b")]+      Data.Multimap.Table.filter (> "c") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"+      Data.Multimap.Table.filter (> "d") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === empty+      filterRow even (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"+      filterColumn (> 'a') (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"+      filterWithKeys (\r c a -> odd r && c > 'a' && a > "b") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"+      mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])+        === fromList [(1,'a',"new a"),(2,'b',"new a")]+      let f r c a = if r == 1 && a == "c" then Just "new c" else Nothing in do+        mapMaybeWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "new c"+      mapEither (\a -> if a == "a" then Left a else Right a) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])+        === (fromList [(1,'a',"a"),(2,'b',"a")],fromList [(1,'b',"c")])+      mapEitherWithKeys (\r c a -> if r == 1 && c == 'a' then Left a else Right a) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])+        === (fromList [(1,'a',"a")],fromList [(1,'b',"c"),(2,'b',"a")])
− test/hspec/Data/Multimap/TableSpec.hs
@@ -1,141 +0,0 @@--- Generated code, do not modify by hand. Generate by running "stack build && stack exec test-gen".--{-# OPTIONS_GHC -w #-}-module Data.Multimap.TableSpec where--import Test.Hspec-import qualified Data.List.NonEmpty as NonEmpty-import qualified Data.Map as Map-import qualified Data.Set as Set-import Data.Multimap.Table--(===) :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation-(===) = shouldBe--spec :: Spec-spec = do-  describe "Testing Data.Multimap.Table" $ do-    it "" $ do-      size empty === 0-      singleton 1 'a' "a" === fromList [(1,'a',"a")]-      size (singleton 1 'a' "a") === 1-      fromList ([] :: [(Int, Char, String)]) === empty-      fromRowMap (Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]), (2, Map.fromList [('a',"d")])])-        === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-      fromColumnMap (Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]), (2, Map.fromList [('a',"d")])])-        === fromList [('a',1,"b"),('a',2,"d"),('b',1,"c")]-      transpose (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [('a',1,"b"),('a',2,"d"),('b',1,"c")]-      insert 1 'a' "a" empty === singleton 1 'a' "a"-      insert 1 'a' "a" (fromList [(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"d")]-      insert 1 'a' "a" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"d")]-      delete 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'b',"c"),(2,'a',"d")]-      delete 1 'a' (fromList [(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'b',"c"),(2,'a',"d")]-      deleteRow 1 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"-      deleteRow 3 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-      deleteColumn 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"-      deleteColumn 'z' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-      adjust ("new " ++) 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === fromList [(1,'a',"new b"),(1,'b',"c"),(2,'a',"d")]-      adjustWithKeys (\r c x -> show r ++ ":" ++ show c ++ ":new " ++ x) 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])-        === fromList [(1,'a',"1:'a':new b"),(1,'b',"c"),(2,'a',"d")]-      let f x = if x == "b" then Just "new b" else Nothing in do-        update f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"new b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        update f 1 'a' (fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-      let f r c x = if x == "b" then Just (show r ++ ":" ++ show c ++ ":new b") else Nothing in do-        updateWithKeys f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"1:'a':new b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        updateWithKeys f 1 'a' (fromList [(1,'a',"a"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-      let (f,g,h) = (const Nothing, const (Just "hello"), fmap ('z':)) in do-        alter f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        alter f 4 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        alter f 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        alter g 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"hello"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        alter g 4 'e' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c"),(4,'e',"hello")]-        alter h 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"zb"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        alter h 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-      let (f,g) = (\_ _ _ -> Nothing, \r c -> fmap ((show r ++ ":" ++ show c ++ ":") ++)) in do-        alterWithKeys f 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        alterWithKeys f 4 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        alterWithKeys f 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        alterWithKeys g 1 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"1:'a':b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-        alterWithKeys g 2 'b' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]) === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(3,'a',"c")]-      fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] !? (1,'a') === Just "b"-      fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] !? (1,'c') === Nothing-      fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")] ! (1,'a') === "b"-      hasCell (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (1,'a') === True-      hasCell (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (1,'c') === False-      hasRow (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 1 === True-      hasRow (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 3 === False-      hasColumn (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 'a' === True-      hasColumn (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) 'c' === False-      Data.Multimap.Table.null empty === True-      Data.Multimap.Table.null (singleton 1 'a' "a") === False-      notNull empty === False-      notNull (singleton 1 'a' "a") === True-      size empty === 0-      size (singleton 1 'a' "a") === 1-      size (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === 3-      union (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])-        === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-      unions [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]-        === fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-      unionWith (++) (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])-        === fromList [(1,'a',"bc"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-      let f r c a a' = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ a' in do-        unionWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")])-          === fromList [(1,'a',"1:'a':b|c"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-      unionsWith (++) [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]-        === fromList [(1,'a',"bc"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-      let f r c a a' = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ a' in do-        unionsWithKeys f [fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")], fromList [(1,'a',"c"),(2,'b',"d"),(3,'c',"e")]]-          === fromList [(1,'a',"1:'a':b|c"),(1,'b',"c"),(2,'a',"b"),(2,'b',"d"),(3,'c',"e")]-      difference (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) (fromList [(1,'a',"c"),(1,'b',"d"),(2,'b',"b")])-        === singleton 2 'a' "b"-      Data.Multimap.Table.map (++ "x") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === fromList [(1,'a',"bx"),(1,'b',"cx"),(2,'a',"bx")]-      mapWithKeys (\r c x -> show r ++ ":" ++ show c ++ ":" ++ x) (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")])-        === fromList [(1,'a',"1:'a':b"),(1,'b',"1:'b':c"),(2,'a',"2:'a':b")]-      let f r c a = if odd r && c > 'a' then Just (a ++ "x") else Nothing in do-        traverseWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"b")]) === Nothing-        traverseWithKeys f (fromList [(1,'b',"b"),(1,'c',"c"),(3,'d',"b")]) === Just (fromList [(1,'b',"bx"),(1,'c',"cx"),(3,'d',"bx")])-      Data.Multimap.Table.foldr (:) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "bcd"-      Data.Multimap.Table.foldl (flip (:)) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "dcb"-      let f r c a b = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ b in do-        foldrWithKeys f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"-      let f a r c b = show r ++ ":" ++ show c ++ ":" ++ b ++ "|" ++ a in do-        foldlWithKeys f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "2:'a':d|1:'b':c|1:'a':b|"-      Data.Multimap.Table.foldr' (:) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "bcd"-      Data.Multimap.Table.foldl' (flip (:)) "" (fromList [(1,'a','b'),(1,'b','c'),(2,'a','d')]) === "dcb"-      let f r c a b = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" ++ b in do-        foldrWithKeys' f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"-      let f a r c b = show r ++ ":" ++ show c ++ ":" ++ b ++ "|" ++ a in do-        foldlWithKeys' f "" (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "2:'a':d|1:'b':c|1:'a':b|"-      let f r c a = show r ++ ":" ++ show c ++ ":" ++ a ++ "|" in do-        foldMapWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === "1:'a':b|1:'b':c|2:'a':d|"-      row 1 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.fromList [('a',"b"),('b',"c")]-      row 3 (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.empty-      column 'a' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.fromList [(1,"b"),(2,"d")]-      column 'c' (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Map.empty-      rowMap (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])-        === Map.fromList [(1, Map.fromList [('a',"b"),('b',"c")]),(2, Map.fromList [('a',"d")])]-      columnMap (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")])-        === Map.fromList [('a', Map.fromList [(1,"b"),(2,"d")]),('b', Map.fromList [(1,"c")])]-      rowKeys (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [1,2]-      columnKeys (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === ['a','b']-      rowKeysSet (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Set.fromList [1,2]-      columnKeysSet (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === Set.fromList ['a','b']-      toList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-      toRowAscList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]-      toColumnAscList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [('a',1,"b"),('a',2,"d"),('b',1,"c")]-      toRowDescList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [(2,'a',"d"),(1,'b',"c"),(1,'a',"b")]-      toColumnDescList (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === [('b',1,"c"),('a',2,"d"),('a',1,"b")]-      Data.Multimap.Table.filter (> "c") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"-      Data.Multimap.Table.filter (> "d") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === empty-      filterRow even (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 2 'a' "d"-      filterColumn (> 'a') (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"-      filterWithKeys (\r c a -> odd r && c > 'a' && a > "b") (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "c"-      mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])-        === fromList [(1,'a',"new a"),(2,'b',"new a")]-      let f r c a = if r == 1 && a == "c" then Just "new c" else Nothing in do-        mapMaybeWithKeys f (fromList [(1,'a',"b"),(1,'b',"c"),(2,'a',"d")]) === singleton 1 'b' "new c"-      mapEither (\a -> if a == "a" then Left a else Right a) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])-        === (fromList [(1,'a',"a"),(2,'b',"a")],fromList [(1,'b',"c")])-      mapEitherWithKeys (\r c a -> if r == 1 && c == 'a' then Left a else Right a) (fromList [(1,'a',"a"),(1,'b',"c"),(2,'b',"a")])-        === (fromList [(1,'a',"a")],fromList [(1,'b',"c"),(2,'b',"a")])
test/hspec/Data/MultimapSpec.hs view
@@ -1,4 +1,4 @@--- Generated code, do not modify by hand. Generate by running "stack build && stack exec test-gen".+-- Generated code, do not modify by hand. Generate by running TestGen.hs.  {-# OPTIONS_GHC -w #-} module Data.MultimapSpec where@@ -7,7 +7,8 @@ import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Map as Map import qualified Data.Set as Set-import Data.Multimap+import Data.Multimap as Data.Multimap+import qualified Data.Multimap.Set as Data.Multimap.Set  (===) :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation (===) = shouldBe@@ -16,126 +17,5 @@ spec = do   describe "Testing Data.Multimap" $ do     it "" $ do-      size empty === 0-      singleton 1 'a' === fromList [(1, 'a')]-      size (singleton 1 'a') === 1-      fromList ([] :: [(Int, Char)]) === empty-      fromMap' (Map.fromList [(1, "ab"), (2, ""), (3, "c")]) === fromList [(1, 'a'), (1, 'b'), (3, 'c')]-      insert 1 'a' empty === singleton 1 'a'-      insert 1 'a' (fromList [(2, 'b'), (2, 'c')]) === fromList [(1, 'a'), (2, 'b'), (2, 'c')]-      insert 1 'a' (fromList [(1, 'b'), (2, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]-      delete 1 (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === singleton 2 'c'-      deleteWithValue 1 'c' (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]-      deleteWithValue 1 'c' (fromList [(1, 'a'), (1, 'b'), (2, 'c'), (1, 'c')]) === fromList [(1, 'a'), (1, 'b'), (2, 'c')]-      deleteWithValue 1 'c' (fromList [(2, 'c'), (1, 'c')]) === singleton 2 'c'-      deleteOne 1 (fromList [(1, 'a'), (1, 'b'), (2, 'c')]) === fromList [(1, 'b'), (2, 'c')]-      deleteOne 1 (fromList [(2, 'c'), (1, 'c')]) === singleton 2 'c'-      adjust ("new " ++) 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"new a"),(1,"new b"),(2,"c")]-      adjustWithKey (\k x -> show k ++ ":new " ++ x) 1 (fromList [(1,"a"),(1,"b"),(2,"c")])-        === fromList [(1,"1:new a"),(1,"1:new b"),(2,"c")]-      let f x = if x == "a" then Just "new a" else Nothing in do-        update f 1 (fromList [(1,"a"),(1, "b"),(2,"c")]) === fromList [(1,"new a"),(2, "c")]-        update f 1 (fromList [(1,"b"),(1, "b"),(2,"c")]) === singleton 2 "c"-      update' NonEmpty.tail 1 (fromList [(1, "a"), (1, "b"), (2, "c")]) === fromList [(1, "b"), (2, "c")]-      update' NonEmpty.tail 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"-      let f k x = if x == "a" then Just (show k ++ ":new a") else Nothing in do-        updateWithKey f 1 (fromList [(1,"a"),(1,"b"),(2,"c")]) === fromList [(1,"1:new a"),(2,"c")]-        updateWithKey f 1 (fromList [(1,"b"),(1,"b"),(2,"c")]) === singleton 2 "c"-      let f k xs = if NonEmpty.length xs == 1 then (show k : NonEmpty.toList xs) else [] in do-        updateWithKey' f 1 (fromList [(1, "a"), (1, "b"), (2, "c")]) === singleton 2 "c"-        updateWithKey' f 1 (fromList [(1, "a"), (2, "b"), (2, "c")]) === fromList [(1, "1"), (1, "a"), (2, "b"), (2, "c")]-      let (f, g) = (const [], ('c':)) in do-        alter f 1 (fromList [(1, 'a'), (2, 'b')]) === singleton 2 'b'-        alter f 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b')]-        alter g 1 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'c'), (1, 'a'), (2, 'b')]-        alter g 3 (fromList [(1, 'a'), (2, 'b')]) === fromList [(1, 'a'), (2, 'b'), (3, 'c')]-      let (f, g) = (const (const []), (:) . show) in do-        alterWithKey f 1 (fromList [(1, "a"), (2, "b")]) === singleton 2 "b"-        alterWithKey f 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b")]-        alterWithKey g 1 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "1"), (1, "a"), (2, "b")]-        alterWithKey g 3 (fromList [(1, "a"), (2, "b")]) === fromList [(1, "a"), (2, "b"), (3, "3")]-      fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 3 === "ac"-      fromList [(3, 'a'), (5, 'b'), (3, 'c')] ! 2 === []-      member 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === True-      member 1 (deleteOne 1 (fromList [(2, 'c'), (1, 'c')])) === False-      notMember 1 (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === False-      notMember 1 (deleteOne 1 (fromList [(2, 'c'), (1, 'c')])) === True-      Data.Multimap.null empty === True-      Data.Multimap.null (singleton 1 'a') === False-      notNull empty === False-      notNull (singleton 1 'a') === True-      size empty === 0-      size (singleton 1 'a') === 1-      size (fromList [(1, 'a'), (2, 'b'), (2, 'c')]) === 3-      union (fromList [(1,'a'),(2,'b'),(2,'c')]) (fromList [(1,'d'),(2,'b')])-        === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c'),(2,'b')]-      unions [fromList [(1,'a'),(2,'b'),(2,'c')], fromList [(1,'d'),(2,'b')]]-        === fromList [(1,'a'),(1,'d'),(2,'b'),(2,'c'),(2,'b')]-      difference (fromList [(1,'a'),(2,'b'),(2,'c'),(2,'b')]) (fromList [(1,'d'),(2,'b'),(2,'a')])-        === fromList [(1,'a'), (2,'c'), (2,'b')]-      Data.Multimap.map (++ "x") (fromList [(1,"a"),(1,"a"),(2,"b")]) === fromList [(1,"ax"),(1,"ax"),(2,"bx")]-      mapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1,"a"),(1,"a"),(2,"b")]) === fromList [(1,"1:a"),(1,"1:a"),(2,"2:b")]-      let f k a = if odd k then Just (succ a) else Nothing in do-        traverseWithKey f (fromList [(1, 'a'), (1, 'b'), (3, 'b'), (3, 'c')]) === Just (fromList [(1, 'b'), (1, 'c'), (3, 'c'), (3, 'd')])-        traverseWithKey f (fromList [(1, 'a'), (1, 'b'), (2, 'b')]) === Nothing-      Data.Multimap.foldr ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-      Data.Multimap.foldl (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-      foldrWithKey (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-      foldlWithKey (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-      Data.Multimap.foldr' ((+) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-      Data.Multimap.foldl' (\len -> (+ len) . length) 0 (fromList [(1, "hello"), (1, "world"), (2, "!")]) === 11-      foldrWithKey' (\k a len -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-      foldlWithKey' (\len k a -> length (show k) + length a + len) 0 (fromList [(1, "hello"), (1, "world"), (20, "!")]) === 15-      foldMapWithKey (\k x -> show k ++ ":" ++ x) (fromList [(1, "a"), (1, "a"), (2, "b")]) === "1:a1:a2:b"-      elems (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === "bbac"-      elems (empty :: Multimap Int Char) === []-      keys (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === [1,2,3]-      keys (empty :: Multimap Int Char) === []-      keysSet (fromList [(2, 'a'), (1, 'b'), (3, 'c'), (1, 'b')]) === Set.fromList [1,2,3]-      keysSet (empty :: Multimap Int Char) === Set.empty-      assocs (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]-      toList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]-      toAscList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(1,'b'),(1,'a'),(2,'a'),(3,'c')]-      toDescList (fromList [(2,'a'),(1,'b'),(3,'c'),(1,'a')]) === [(3,'c'),(2,'a'),(1,'b'),(1,'a')]-      toAscListBF (fromList [("Foo",1),("Foo",2),("Foo",3),("Bar",4),("Bar",5),("Baz",6)])-        === [("Bar",4),("Baz",6),("Foo",1),("Bar",5),("Foo",2),("Foo",3)]-      toDescListBF (fromList [("Foo",1),("Foo",2),("Foo",3),("Bar",4),("Bar",5),("Baz",6)])-        === [("Foo",1),("Baz",6),("Bar",4),("Foo",2),("Bar",5),("Foo",3)]-      Data.Multimap.filter (> 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 1 'b'-      Data.Multimap.filter (< 'a') (fromList [(1,'a'),(1,'b'),(2,'a')]) === empty-      filterKey even (fromList [(1,'a'),(1,'b'),(2,'a')]) === singleton 2 'a'-      filterWithKey (\k a -> even k && a > 'a') (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'b')]) === singleton 2 'b'-      let f a | a > 'b' = Just True-              | a < 'b' = Just False-              | a == 'b' = Nothing-       in do-         filterM f (fromList [(1,'a'),(1,'b'),(2,'a'),(2,'c')]) === Nothing-         filterM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Just (fromList [(1,'c'),(2,'c')])-      let f k a | even k && a > 'b' = Just True-                | odd k && a < 'b' = Just False-                | otherwise = Nothing-       in do-         filterWithKeyM f (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')]) === Nothing-         filterWithKeyM f (fromList [(1,'a'),(1,'a'),(2,'c'),(2,'c')]) === Just (fromList [(2,'c'),(2,'c')])-      mapMaybe (\a -> if a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])-        === fromList [(1,"new a"),(2,"new a")]-      mapMaybeWithKey (\k a -> if k > 1 && a == "a" then Just "new a" else Nothing) (fromList [(1,"a"),(1,"b"),(2,"a"),(2,"c")])-        === singleton 2 "new a"-      mapEither (\a -> if a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])-        === (fromList [(1,'a'),(2,'a')],fromList [(1,'c'),(2,'c')])-      mapEitherWithKey (\k a -> if even k && a < 'b' then Left a else Right a) (fromList [(1,'a'),(1,'c'),(2,'a'),(2,'c')])-        === (fromList [(2,'a')],fromList [(1,'a'),(1,'c'),(2,'c')])-      lookupMin (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (1, NonEmpty.fromList "ac")-      lookupMin (empty :: Multimap Int Char) === Nothing-      lookupMax (fromList [(1,'a'),(1,'c'),(2,'c')]) === Just (2, NonEmpty.fromList "c")-      lookupMax (empty :: Multimap Int Char) === Nothing-      lookupLT 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing-      lookupLT 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")-      lookupGT 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing-      lookupGT 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")-      lookupLE 0 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing-      lookupLE 1 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (1, NonEmpty.fromList "a")-      lookupLE 4 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")-      lookupGE 6 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Nothing-      lookupGE 5 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (5, NonEmpty.fromList "c")-      lookupGE 2 (fromList [(1,'a'),(3,'b'),(3,'c'),(5,'c')]) === Just (3, NonEmpty.fromList "bc")+      fromSetMultimapAsc (Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.fromList [(1,'a'),(1,'b'),(2,'c')]+      fromSetMultimapDesc (Data.Multimap.Set.fromList [(1,'a'),(1,'b'),(2,'c')]) === Data.Multimap.fromList [(1,'b'),(1,'a'),(2,'c')]