-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | An efficient and versatile range library. -- -- The range library alows the use of performant and versatile ranges in -- your code. It supports bounded and unbounded ranges, ranges in a -- nested manner (like library versions), an efficient algebra of range -- computation and even a simplified interface for ranges for the common -- cases. This library is far more efficient than using the default -- Data.List functions to approximate range behaviour. Performance is the -- major value offering of this library. If this is your first time using -- this library it is highly recommended that you start with -- Data.Range.Range; it contains the basics of this library that -- meet most use cases. @package range @version 0.2.1.0 -- | Internally the range library converts your ranges into an internal -- efficient representation of multiple ranges. When you do multiple -- unions and intersections in a row converting to and from that data -- structure becomes extra work that is not required. To amortize those -- costs away the RangeExpr algebra exists. You can specify a -- tree of operations in advance and then evaluate them all at once. This -- is not only useful for efficiency but for parsing too. Build up -- RangeExpr's whenever you wish to perform multiple operations -- in a row, and evaluate it in one step to be as efficient as possible. -- -- Note: This module is based on F-Algebras to do much of the -- heavy conceptual lifting. If you have never seen F-Algebras before -- then I highly recommend reading through this introductory -- content from the School of Haskell. -- --

Examples

-- -- A simple example of using this module would look like this: -- --
--   ghci> import qualified Data.Range.Algebra as A
--   ghci> (A.eval . A.invert $ A.const [SingletonRange 5]) :: [Range Integer]
--   [LowerBoundRange 6,UpperBoundRange 4]
--   (0.01 secs, 597,656 bytes)
--   ghci>
--   
-- -- You can also use this module to evaluate range predicates. module Data.Range.Algebra data RangeExpr a -- | Lifts the input value as a constant into an expression. const :: a -> RangeExpr a -- | Returns an expression that represents the inverse of the input -- expression. invert :: RangeExpr a -> RangeExpr a -- | Returns an expression that represents the set union of the input -- expressions. union :: RangeExpr a -> RangeExpr a -> RangeExpr a -- | Returns an expression that represents the set intersection of the -- input expressions. intersection :: RangeExpr a -> RangeExpr a -> RangeExpr a -- | Returns an expression that represents the set difference of the input -- expressions. difference :: RangeExpr a -> RangeExpr a -> RangeExpr a -- | This is an F-Algebra. You don't need to know what this is in order to -- be able to use this module, but, if you are interested you can read -- more on School of Haskell. type Algebra f a = f a -> a -- | Represents the fact that there exists an algebra for the given -- representation of a range, so that a range expression of the same type -- can be evaluated, yielding that representation. class RangeAlgebra a -- | This function is used to convert your built expressions into ranges. eval :: RangeAlgebra a => Algebra RangeExpr a instance (GHC.Classes.Ord a, GHC.Enum.Enum a) => Data.Range.Algebra.RangeAlgebra [Data.Range.Data.Range a] instance Data.Range.Algebra.RangeAlgebra (a -> GHC.Types.Bool) -- | Deprecated: Use Data.Range.Algebra instead module Data.Range.RangeTree -- | Evaluates a Range Tree into the final set of ranges that it compresses -- down to. Use this whenever you want to finally evaluate your -- constructed Range Tree. evaluate :: (Ord a, Enum a) => RangeTree a -> [Range a] -- | A Range Tree is a construct that can be built and then efficiently -- evaluated so that you can compress an entire tree of operations on -- ranges into a single range quickly. The only purpose of this tree is -- to allow efficient construction of range operations that can be -- evaluated as is required. data RangeTree a -- | Combine two range trees together with a single operation RangeNode :: RangeOperation -> (RangeTree a) -> (RangeTree a) -> RangeTree a -- | Invert a range tree, this is a not operation. RangeNodeInvert :: (RangeTree a) -> RangeTree a -- | A leaf with a set of ranges that are collected together. RangeLeaf :: [Range a] -> RangeTree a -- | These are the operations that can join two disjunct lists of ranges -- together. data RangeOperation -- | Represents the set union operation. RangeUnion :: RangeOperation -- | Represents the set intersection operation. RangeIntersection :: RangeOperation -- | Represents the set difference operation. RangeDifference :: RangeOperation -- | This module provides a simple api to access range functionality. It -- provides standard set operations on ranges, the ability to merge -- ranges together and, importantly, the ability to check if a value is -- within a range. -- -- Note: It is intended that you will read the documentation in -- this module from top to bottom. module Data.Range.Range -- | The Range Data structure; it is capable of representing any type of -- range. This is the primary data structure in this library. Everything -- should be possible to convert back into this datatype. All ranges in -- this structure are inclusively bound. data Range a -- | Represents a single element as a range. SingletonRange :: a -> Range a -- | Represents a bounded and inclusive range of elements. SpanRange :: a -> a -> Range a -- | Represents a range with only an inclusive lower bound. LowerBoundRange :: a -> Range a -- | Represents a range with only an inclusive upper bound. UpperBoundRange :: a -> Range a -- | Represents an infinite range over all values. InfiniteRange :: Range a -- | Given a range and a value it will tell you wether or not the value is -- in the range. Remember that all ranges are inclusive. -- -- The primary value of this library is performance and this method can -- be used to show 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: -- --
--   ghci> :set +s
--   ghci> elem (10000000 :: Integer) [1..10000000]
--   True
--   (0.26 secs, 720,556,888 bytes)
--   ghci> inRange (SpanRange 1 10000000) (10000000 :: Integer)
--   True
--   (0.00 secs, 557,656 bytes)
--   ghci>
--   
-- -- As you can see, this function is significantly more performant, in -- both speed and memory, than using the elem function. inRange :: (Ord a) => Range a -> a -> Bool -- | Given a list of ranges this function tells you if a value is in any of -- those ranges. This is especially useful for more complex ranges. inRanges :: (Ord a) => [Range a] -> a -> Bool -- | A check to see if two ranges overlap. If they do then true is -- returned; false otherwise. rangesOverlap :: (Ord a) => Range a -> Range a -> Bool -- | An array of ranges may have overlaps; this function will collapse that -- array into as few Ranges as possible. For example: -- --
--   ghci> mergeRanges [LowerBoundRange 12, SpanRange 1 10, SpanRange 5 (15 :: Integer)]
--   [LowerBoundRange 1]
--   (0.01 secs, 588,968 bytes)
--   ghci>
--   
-- -- As you can see, the mergeRanges method collapsed multiple ranges into -- a single range that still covers the same surface area. -- -- This may be useful for a few use cases: -- -- -- -- Please note that the use of any of the operations on sets of ranges -- like invert, union and intersection will have the same behaviour as -- mergeRanges as a side effect. So, for example, this is redundant: -- --
--   mergeRanges . intersection []
--   
mergeRanges :: (Ord a, Enum a) => [Range a] -> [Range a] -- | Performs a set union between the two input ranges and returns the -- resultant set of ranges. -- -- For example: -- --
--   ghci> union [SpanRange 1 10] [SpanRange 5 (15 :: Integer)]
--   [SpanRange 1 15]
--   (0.00 secs, 587,152 bytes)
--   ghci>
--   
union :: (Ord a, Enum a) => [Range a] -> [Range a] -> [Range a] -- | Performs a set intersection between the two input ranges and returns -- the resultant set of ranges. -- -- For example: -- --
--   ghci> intersection [SpanRange 1 10] [SpanRange 5 (15 :: Integer)]
--   [SpanRange 5 10]
--   (0.00 secs, 584,616 bytes)
--   ghci>
--   
intersection :: (Ord a, Enum a) => [Range a] -> [Range a] -> [Range a] -- | Performs a set difference between the two input ranges and returns the -- resultant set of ranges. -- -- For example: -- --
--   ghci> difference [SpanRange 1 10] [SpanRange 5 (15 :: Integer)]
--   [SpanRange 1 4]
--   (0.00 secs, 590,424 bytes)
--   ghci>
--   
difference :: (Ord a, Enum a) => [Range a] -> [Range a] -> [Range a] -- | An inversion function, given a set of ranges it returns the inverse -- set of ranges. -- -- For example: -- --
--   ghci> invert [SpanRange 1 10, SpanRange 15 (20 :: Integer)]
--   [LowerBoundRange 21,UpperBoundRange 0,SpanRange 11 14]
--   (0.00 secs, 623,456 bytes)
--   ghci>
--   
invert :: (Ord a, Enum a) => [Range a] -> [Range a] -- | Instantiate all of the values in a range. -- -- Warning: This method is meant as a convenience method, it is -- not efficient. -- -- A set of ranges represents a collection of real values without -- actually instantiating those values. Not instantiating ranges, allows -- the range library to support infinite ranges and be super performant. -- -- However, sometimes you actually want to get the values that your range -- represents, or even get a sample set of the values. This function -- generates as many of the values that belong to your range as you like. -- -- Because ranges can be infinite, it is highly recommended to combine -- this method with something like "Data.List.take" to avoid an infinite -- recursion. -- --

Examples

-- -- A simple span: -- --
--   ghci> take 5 . fromRanges $ [SpanRange 1 10 :: Range Integer]
--   [1,2,3,4,5]
--   (0.01 secs, 566,016 bytes)
--   ghci>
--   
-- -- An infinite range: -- --
--   ghci> take 5 . fromRanges $ [InfiniteRange :: Range Integer]
--   [0,1,-1,2,-2]
--   (0.00 secs, 566,752 bytes)
--   ghci>
--   
fromRanges :: (Ord a, Enum a) => [Range a] -> [a] -- | This package provides a simple range parser. -- -- This range parser was designed to be a useful tool for CLI programs. -- For example, by default, this example depicts how the parser works: -- --
--   ghci> parseRanges "-5,8-10,13-15,20-" :: Either ParseError [Range Integer]
--   Right [UpperBoundRange 5,SpanRange 8 10,SpanRange 13 15,LowerBoundRange 20]
--   (0.01 secs, 681,792 bytes)
--   ghci>
--   
-- -- And the * character translates to an infinite range. This is very -- useful for accepting ranges as input in CLI programs, but not as -- useful for parsing .cabal or package.json files. -- -- To handle more complex parsing cases it is recommended that you use -- the ranges library in conjunction with parsec or Alex/Happy and -- convert the versions that you find into ranges. module Data.Range.Parser -- | Given a string, this function will either return a parse error back to -- the user or the list of ranges that are represented by the parsed -- string. Very useful for CLI programs that need to load ranges from a -- single-line string. parseRanges :: (Read a) => String -> Either ParseError [Range a] -- | If you disagree with the default characters for separating ranges then -- this function can be used to customise them, up to a point. customParseRanges :: Read a => RangeParserArgs -> String -> Either ParseError [Range a] -- | These are the arguments that will be used when parsing a string as a -- range. data RangeParserArgs Args :: String -> String -> String -> RangeParserArgs -- | A separator that represents a union. [unionSeparator] :: RangeParserArgs -> String -- | A separator that separates the two halves of a range. [rangeSeparator] :: RangeParserArgs -> String -- | A separator that implies an unbounded range. [wildcardSymbol] :: RangeParserArgs -> String -- | These are the default arguments that are used by the parser. Please -- feel free to use the default arguments for you own parser and modify -- it from the defaults at will. defaultArgs :: RangeParserArgs -- | Given the parser arguments this returns a parsec parser that is -- capable of parsing a list of ranges. ranges :: (Read a) => RangeParserArgs -> Parser [Range a] -- | The abstract data type ParseError represents parse errors. It -- provides the source position (SourcePos) of the error and a -- list of error messages (Message). A ParseError can be -- returned by the function parse. ParseError is an -- instance of the Show and Eq classes. data ParseError instance GHC.Show.Show Data.Range.Parser.RangeParserArgs -- | Nested Ranges are common in practical usage. They appear in such forms -- as library version numbers ("Version 1.4.5.6" for example). -- -- It is very useful to be able to compare these ranges to one another. -- This module exists for the purpose of allowing these comparisons -- between nested ranges. The module builds upon the basic range concept -- from other parts of this library. module Data.Range.NestedRange -- | The Nested Range is a structure that in a nested form of many ranges -- where there can be multiple ranges at every level. -- -- For example, saying that you require a minimum version of 1.2.3 could -- be represented as: -- --
--   NestedRange [[LowerBoundRange 1],[LowerBoundRange 2],[LowerBoundRange 3]]
--   
data NestedRange a NestedRange :: [[Range a]] -> NestedRange a -- | This method converts the Data.Version datatype into a -- NestedRange. -- -- For example: -- --
--   ghci> fromVersion LowerBoundRange (Version [1, 2, 3] [])
--   NestedRange [[LowerBoundRange 1],[LowerBoundRange 2],[LowerBoundRange 3]]
--   (0.01 secs, 624,736 bytes)
--   ghci>
--   
fromVersion :: (Int -> Range Int) -> Version -> NestedRange Int -- | Given a list of nested values and a nested range tell us wether the -- nested value exists inside the nested range. -- --

Examples

-- -- In a simple case: -- --
--   ghci> inNestedRange [2, 8, 3] (NestedRange [[SpanRange 1 2]] :: NestedRange Integer)
--   True
--   (0.01 secs, 558,400 bytes)
--   ghci>
--   
-- -- Not in the bounds: -- --
--   ghci> inNestedRange [2, 8, 3] (NestedRange [[SpanRange 1 2], [UpperBoundRange 7]] :: NestedRange Integer)
--   False
--   (0.00 secs, 558,896 bytes)
--   ghci>
--   
-- -- For something based on Data.Version: -- --
--   ghci> version = Version [2, 8, 3] []
--   ghci> upperBound = Version [2, 7] []
--   ghci> inNestedRange (versionBranch version) (fromVersion UpperBoundRange upperBound)
--   False
--   ghci>
--   ghci> inNestedRange (versionBranch version) (fromVersion LowerBoundRange upperBound)
--   True
--   ghci>
--   
inNestedRange :: Ord a => [a] -> NestedRange a -> Bool instance GHC.Show.Show a => GHC.Show.Show (Data.Range.NestedRange.NestedRange a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Range.NestedRange.NestedRange a)