packages feed

range 0.3.2.1 → 0.3.2.2

raw patch · 10 files changed

+67/−45 lines, 10 files

Files

Data/Range.hs view
@@ -85,17 +85,19 @@ -- of this. For example, let's say that you want to say: "I accept a version range of [1.1.0, 1.2.1] or [1.3, 1.4) or [1.4, 1.4.2)" -- then you can write that as: ----- >>> :m + Data.Version--- >>> let v x = Version x []--- >>> let ranges = mergeRanges [v [1, 1, 0] +=+ v [1,2,1], v [1,3] +=* v [1,4], v [1,4] +=* v [1,4,2]]--- >>> inRanges ranges (v [1,0])+-- @+-- \>\>\> :m + Data.Version+-- \>\>\> let v x = Version x []+-- \>\>\> let ranges = mergeRanges [v [1, 1, 0] +=+ v [1,2,1], v [1,3] +=* v [1,4], v [1,4] +=* v [1,4,2]]+-- \>\>\> inRanges ranges (v [1,0]) -- False--- >>> inRanges ranges (v [1,5])+-- \>\>\> inRanges ranges (v [1,5]) -- False--- >>> inRanges ranges (v [1,1,5])+-- \>\>\> inRanges ranges (v [1,1,5]) -- True--- >>> inRanges ranges (v [1,3,5])+-- \>\>\> inRanges ranges (v [1,3,5]) -- True+-- @ -- -- As you can see, it is almost identical to the previous example, yet you are now comparing if a version is within a version range! -- Not only that, but so long as your type is orderable, the ranges can be merged together cleanly.@@ -136,6 +138,9 @@       Range(..)    ) where +-- $setup+-- >>> import Data.Range+ import Data.Range.Data import Data.Range.Operators import Data.Range.Util@@ -222,21 +227,20 @@ rangesOverlapType InfiniteRange _ = Overlap rangesOverlapType a b = rangesOverlapType b a --- | A check to see if two ranges overlap or adjoin. The ranges adjoin if no values exist between them.---  If they do overlap or adjoin then true is returned; false otherwise.+-- | A check to see if two ranges adjoin. Ranges adjoin if they share no values but touch at a+-- single boundary point — exactly one of the touching bounds is exclusive. -- -- For example: ----- >>> rangesAdjoin (1 +=+ 5) (3 +=+ 7)--- True--- >>> rangesAdjoin (1 +=+ 5) (5 +=+ 7)--- True -- >>> rangesAdjoin (1 +=* 5) (5 +=+ 7) -- True+-- >>> rangesAdjoin (1 +=+ 5) (5 *=+ 7)+-- True+-- >>> rangesAdjoin (1 +=+ 5) (3 +=+ 7)+-- False ----- The last case of these three is the primary "gotcha" of this method. With @[1, 5)@ and @[5, 7]@ there--- exist no values between them. Therefore the ranges adjoin. If you expected this to return False then--- it is likely that you would prefer to use 'rangesOverlap' instead.+-- The third case illustrates the distinction from 'rangesOverlap': @[1, 5]@ and @[3, 7]@ share+-- values 3–5, so they overlap, not adjoin. See also 'rangesOverlap'. rangesAdjoin :: (Ord a) => Range a -> Range a -> Bool rangesAdjoin a b = Adjoin == (rangesOverlapType a b) @@ -249,14 +253,15 @@ -- this quite clearly. For example, you can try and approximate basic range functionality -- with "Data.List.elem" so we can generate an apples to apples comparison in GHCi: ----- >>> :set +s--- >>> elem (10000000 :: Integer) [1..10000000]+-- @+-- \>\>\> :set +s+-- \>\>\> elem (10000000 :: Integer) [1..10000000] -- True -- (0.26 secs, 720,556,888 bytes)--- >>> inRange (1 +=+ 10000000) (10000000 :: Integer)+-- \>\>\> inRange (1 +=+ 10000000) (10000000 :: Integer) -- True -- (0.00 secs, 557,656 bytes)--- >>>+-- @ -- -- As you can see, this function is significantly more performant, in both speed and memory, -- than using the elem function.@@ -369,7 +374,6 @@ -- -- >>> mergeRanges [lbi 12, 1 +=+ 10, 5 +=+ (15 :: Integer)] -- [lbi 1]--- (0.01 secs, 588,968 bytes) -- -- As you can see, the mergeRanges method collapsed multiple ranges into a single range that -- still covers the same surface area.@@ -419,13 +423,11 @@ -- -- >>> take 5 . fromRanges $ [1 +=+ 10 :: Range Integer, 20 +=+ 30] -- [1,20,2,21,3]--- (0.01 secs, 566,016 bytes) -- -- An infinite range: -- -- >>> take 5 . fromRanges $ [inf :: Range Integer] -- [0,1,-1,2,-2]--- (0.00 secs, 566,752 bytes) fromRanges :: (Ord a, Enum a) => [Range a] -> [a] fromRanges = takeEvenly . fmap fromRange . mergeRanges    where
Data/Range/Algebra.hs view
@@ -21,18 +21,20 @@ -- -- Evaluate to a concrete list of ranges: ----- >>> import qualified Data.Range.Algebra as A--- >>> import Data.Range--- >>> A.eval . A.invert $ A.const [SingletonRange (5 :: Integer)]--- [ube 4,lbi 6]+-- @+-- import qualified Data.Range.Algebra as A+-- import Data.Range+-- A.eval . A.invert $ A.const [SingletonRange (5 :: Integer)]+-- -- [ube 4,lbi 6]+-- @ -- -- Evaluate the same expression as a predicate (no intermediate list is built): ----- >>> let expr = A.union (A.const [1 +=+ 10]) (A.const [20 +=+ 30]) :: A.RangeExpr [Range Integer]--- >>> (A.eval expr :: Integer -> Bool) 25--- True--- >>> (A.eval expr :: Integer -> Bool) 15--- False+-- @+-- let expr = A.union (A.const [1 +=+ 10]) (A.const [20 +=+ 30]) :: A.RangeExpr [Range Integer]+-- (A.eval expr :: Integer -> Bool) 25  -- True+-- (A.eval expr :: Integer -> Bool) 15  -- False+-- @ -- module Data.Range.Algebra   ( -- * Expression trees
Data/Range/Algebra/Predicate.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} module Data.Range.Algebra.Predicate where  import Control.Applicative
Data/Range/Algebra/Range.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} module Data.Range.Algebra.Range where  import Data.Range.Data
Data/Range/Operators.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} module Data.Range.Operators where  import Data.Range.Data
Data/Range/Ord.hs view
@@ -31,11 +31,14 @@ -- -- == Example: sorting ranges by position on the number line ----- >>> import Data.List (sortOn)--- >>> sortOn SortedRange [lbi 10, 1 +=+ 5, ube 0 :: Range Integer]--- [ube 0,1 +=+ 5,lbi 10]--- -- @+-- import Data.List (sortOn)+-- import Data.Range (Range, (+=+), lbi, ube)+-- import Data.Range.Ord (SortedRange(..))+--+-- sortOn SortedRange [lbi 10, 1 +=+ 5, ube 0 :: Range Integer]+-- -- [ube 0, 1 +=+ 5, lbi 10]+-- -- -- or equivalently: -- displayRanges :: Ord a => [Range a] -> [Range a] -- displayRanges = sortOn SortedRange@@ -52,6 +55,11 @@    , SortedRange(..)    ) where +-- $setup+-- >>> import Data.Range+-- >>> import Data.Range.Ord+-- >>> import Data.List (sortOn)+ import Data.Range.Data import Data.Range.Util (compareLower, compareHigher) @@ -146,8 +154,8 @@ -- Use 'unSortedRange' to unwrap the underlying 'Range'. Typical usage: -- -- >>> import Data.List (sortOn)--- >>> sortOn SortedRange [lbi 10, 1 +=+ 5, ube 0 :: Range Integer]--- [ube 0,1 +=+ 5,lbi 10]+-- >>> sortOn SortedRange [SingletonRange 5, SingletonRange 1, SingletonRange 3 :: Range Integer]+-- [SingletonRange 1,SingletonRange 3,SingletonRange 5] -- -- See also 'KeyRange' for a structural ordering suitable for 'Data.Map.Map' keys. --
Data/Range/Parser.hs view
@@ -5,18 +5,18 @@ -- By default, ranges are separated by commas and span endpoints by a hyphen: -- -- >>> parseRanges "-5,8-10,13-15,20-" :: Either ParseError [Range Integer]--- Right [UpperBoundRange (Bound 5 Inclusive),SpanRange (Bound 8 Inclusive) (Bound 10 Inclusive),SpanRange (Bound 13 Inclusive) (Bound 15 Inclusive),LowerBoundRange (Bound 20 Inclusive)]+-- Right [ubi 5,8 +=+ 10,13 +=+ 15,lbi 20] -- -- The @*@ wildcard produces an infinite range: -- -- >>> parseRanges "*" :: Either ParseError [Range Integer]--- Right [InfiniteRange]+-- Right [inf] -- -- Use 'customParseRanges' to change the separator characters: -- -- >>> let args = defaultArgs { unionSeparator = ";", rangeSeparator = ".." } -- >>> customParseRanges args "1..5;10" :: Either ParseError [Range Integer]--- Right [SpanRange (Bound 1 Inclusive) (Bound 5 Inclusive),SingletonRange 10]+-- Right [1 +=+ 5,SingletonRange 10] -- -- __Known limitations:__ --@@ -47,6 +47,10 @@    , ParseError    ) where +-- $setup+-- >>> import Data.Range+-- >>> import Data.Range.Parser+ import Text.Parsec import Text.Parsec.String @@ -90,7 +94,7 @@ -- -- >>> let args = defaultArgs { unionSeparator = ";", rangeSeparator = ".." } -- >>> customParseRanges args "1..5;10" :: Either ParseError [Range Integer]--- Right [SpanRange (Bound 1 Inclusive) (Bound 5 Inclusive),SingletonRange 10]+-- Right [1 +=+ 5,SingletonRange 10] customParseRanges :: Read a => RangeParserArgs -> String -> Either ParseError [Range a] customParseRanges args = parse (ranges args) "(range parser)" 
Data/Ranges.hs view
@@ -50,6 +50,10 @@   joinRanges ) where +-- $setup+-- >>> import Data.Ranges+-- >>> import Data.Foldable (fold)+ import Data.Semigroup import qualified Data.Range as R 
DocTest.hs view
@@ -4,8 +4,7 @@  main :: IO () main = doctest-   [ "-XSafe"-   , "Data/Range.hs"+   [ "Data/Range.hs"    , "Data/Ranges.hs"    , "Data/Range/Ord.hs"    , "Data/Range/Parser.hs"
range.cabal view
@@ -10,7 +10,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.3.2.1+version:             0.3.2.2  -- A short (one-line) description of the package. synopsis:            An efficient and versatile range library.