multi-containers 0.1.0.2 → 0.1.1
raw patch · 10 files changed
+172/−85 lines, 10 filesdep −directorydep −extradep −filepathdep ~hspecsetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies removed: directory, extra, filepath
Dependency ranges changed: hspec
API changes (from Hackage documentation)
+ Data.Multimap: lookupGE :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)
+ Data.Multimap: lookupGT :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)
+ Data.Multimap: lookupLE :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)
+ Data.Multimap: lookupLT :: Ord k => k -> Multimap k a -> Maybe (k, NonEmpty a)
+ Data.Multimap: lookupMax :: Multimap k a -> Maybe (k, NonEmpty a)
+ Data.Multimap: lookupMin :: Multimap k a -> Maybe (k, NonEmpty a)
+ Data.Multimap.Set: lookupGE :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)
+ Data.Multimap.Set: lookupGT :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)
+ Data.Multimap.Set: lookupLE :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)
+ Data.Multimap.Set: lookupLT :: Ord k => k -> SetMultimap k a -> Maybe (k, Set a)
+ Data.Multimap.Set: lookupMax :: SetMultimap k a -> Maybe (k, Set a)
+ Data.Multimap.Set: lookupMin :: SetMultimap k a -> Maybe (k, Set a)
Files
- ChangeLog.md +4/−0
- LICENSE +2/−2
- Setup.hs +0/−2
- multi-containers.cabal +14/−25
- src/Data/Multimap.hs +62/−3
- src/Data/Multimap/Set.hs +62/−3
- src/Data/Multimap/Table.hs +0/−1
- test-gen/Main.hs +0/−49
- test/hspec/Data/Multimap/SetSpec.hs +14/−0
- test/hspec/Data/MultimapSpec.hs +14/−0
ChangeLog.md view
@@ -1,5 +1,9 @@ # Changelog for multi-containers +## 0.1.1++- Add min/max functions for `Data.Multimap` and `Data.Multimap.Set`.+ ## 0.1.0.2 - Remove redundant constraints
LICENSE view
@@ -1,4 +1,4 @@-Copyright Author name here (c) 2019+Copyright Ziyang Liu (c) 2019-2020. All rights reserved. @@ -13,7 +13,7 @@ disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Author name here nor the names of other+ * Neither the name of the author nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission.
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
multi-containers.cabal view
@@ -1,11 +1,7 @@--- This file has been generated from package.yaml by hpack version 0.28.2.------ see: https://github.com/sol/hpack------ hash: 5c8d0a2541fa360ef1903f422222c873e84c5ea3b0fd709475a4ee54c843bbf8+cabal-version: 2.4 name: multi-containers-version: 0.1.0.2+version: 0.1.1 synopsis: A few multimap variants. description: A library that provides a few multimap variants. category: Data Structures@@ -13,11 +9,12 @@ bug-reports: https://github.com/zliu41/multi-containers/issues author: Ziyang Liu <free@cofree.io> maintainer: Ziyang Liu <free@cofree.io>-copyright: 2019 Ziyang Liu-license: BSD3+copyright: 2019-2020 Ziyang Liu+license: BSD-3-Clause license-file: LICENSE build-type: Simple-cabal-version: >= 1.10+tested-with: GHC==8.10.1, GHC==8.8.2, GHC==8.6.5, GHC==8.4.4+ extra-source-files: ChangeLog.md README.md@@ -33,27 +30,16 @@ Data.Multimap.Table other-modules: Paths_multi_containers+ autogen-modules:+ Paths_multi_containers hs-source-dirs: src+ ghc-options: -Wall build-depends: base >=4.7 && <5 , containers >=0.5.10.2 && <0.7 default-language: Haskell2010 -executable test-gen- main-is: Main.hs- other-modules:- Paths_multi_containers- hs-source-dirs:- test-gen- build-depends:- base >=4.7 && <5- , containers >=0.5.10.2 && <0.7- , directory >=1.3.0.2 && <1.4- , extra >=1.6.9 && <1.7- , filepath >=1.4.1.2 && <1.5- default-language: Haskell2010- test-suite hspec type: exitcode-stdio-1.0 main-is: Main.hs@@ -62,12 +48,15 @@ Data.Multimap.TableSpec Data.MultimapSpec Paths_multi_containers+ autogen-modules:+ Paths_multi_containers hs-source-dirs: test/hspec- ghc-options: -threaded -rtsopts -with-rtsopts=-N+ ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N build-depends: base >=4.7 && <5 , containers >=0.5.10.2 && <0.7- , hspec >=2.4.8 && <2.8+ , hspec >=2.4.8 && <3 , multi-containers default-language: Haskell2010+ build-tool-depends: hspec-discover:hspec-discover == 2.*
src/Data/Multimap.hs view
@@ -135,6 +135,14 @@ , mapMaybeWithKey , mapEither , mapEitherWithKey++ -- * Min\/Max+ , lookupMin+ , lookupMax+ , lookupLT+ , lookupGT+ , lookupLE+ , lookupGE ) where import Control.Arrow ((&&&))@@ -150,7 +158,6 @@ import Data.Map.Lazy (Map) import qualified Data.Map.Lazy as Map import qualified Data.Maybe as Maybe-import Data.Semigroup (Semigroup, (<>)) import Data.Set (Set) import Prelude hiding (filter, foldl, foldr, lookup, map, null)@@ -515,7 +522,7 @@ foldl :: (a -> b -> a) -> a -> Multimap k b -> a foldl = foldlWithKey . (const .) --- | /O(n)/. Fold the key\/value paris in the map using the given+-- | /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@@ -524,7 +531,7 @@ where f' = flip . Foldable.foldr . f --- | /O(n)/. Fold the key\/value paris in the map using the given+-- | /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@@ -743,3 +750,55 @@ $ 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
@@ -133,6 +133,14 @@ , mapMaybeWithKey , mapEither , mapEitherWithKey++ -- * Min\/Max+ , lookupMin+ , lookupMax+ , lookupLT+ , lookupGT+ , lookupLE+ , lookupGE ) where import Prelude hiding (filter, foldl, foldr, lookup, map, null)@@ -145,7 +153,6 @@ import Data.Map.Lazy (Map) import qualified Data.Map.Lazy as Map import qualified Data.Maybe as Maybe-import Data.Semigroup (Semigroup, (<>)) import Data.Set (Set) import qualified Data.Set as Set @@ -472,7 +479,7 @@ foldl :: (a -> b -> a) -> a -> SetMultimap k b -> a foldl = foldlWithKey . (const .) --- | /O(n)/. Fold the key\/value paris in the map using the given+-- | /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@@ -481,7 +488,7 @@ where f' = flip . Set.foldr . f --- | /O(n)/. Fold the key\/value paris in the map using the given+-- | /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@@ -683,6 +690,58 @@ $ 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
src/Data/Multimap/Table.hs view
@@ -131,7 +131,6 @@ import Data.Map (Map) import qualified Data.Map as Map import qualified Data.Maybe as Maybe-import Data.Semigroup (Semigroup, (<>)) import Data.Set (Set) import Prelude hiding (filter, foldl, foldr, lookup, map, null)
− test-gen/Main.hs
@@ -1,49 +0,0 @@-module Main (main) where--import Data.List.Extra (replace, stripPrefix, trim)-import Data.Maybe (mapMaybe)-import System.Directory-import System.FilePath--import Prelude hiding (mod)--main :: IO ()-main = do- genTestsFor "Data.Multimap"- genTestsFor "Data.Multimap.Set"- genTestsFor "Data.Multimap.Table"--genTestsFor :: String -> IO ()-genTestsFor mod = do- let inputFile = "src" </> replace "." [pathSeparator] mod <.> "hs"- outputFile = "test/hspec" </> (replace "." [pathSeparator] mod ++ "Spec.hs")- src <- readFile inputFile- createDirectoryIfMissing True (takeDirectory outputFile)- let lns = fmap trim (lines src)- tests = mapMaybe (stripPrefix "-- > ") lns- writeFile outputFile . unlines $ header mod ++ fmap (indent 6) tests--header :: String -> [String]-header mod =- [ "-- Generated code, do not modify by hand. Generate by running \"stack build && stack exec test-gen\"."- , ""- , "{-# OPTIONS_GHC -w #-}"- , "module " ++ mod ++ "Spec where"- , ""- , "import Test.Hspec"- , "import qualified Data.List.NonEmpty as NonEmpty"- , "import qualified Data.Map as Map"- , "import qualified Data.Set as Set"- ] ++ ["import " ++ mod] ++- [ ""- , "(===) :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation"- , "(===) = shouldBe"- , ""- , "spec :: Spec"- , "spec = do"- , " describe \"Testing " ++ mod ++ "\" $ do"- , " it \"\" $ do"- ]--indent :: Int -> String -> String-indent n = (replicate n ' ' ++)
test/hspec/Data/Multimap/SetSpec.hs view
@@ -115,3 +115,17 @@ === (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/MultimapSpec.hs view
@@ -125,3 +125,17 @@ === (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")