úί„ª©\      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[portable experimentalpaul@cogito.org.uk >A Boundary is a division of an ordered type into values above 9and below the boundary. No value can sit on a boundary. Known bug: for Bounded types  BoundaryAbove maxBound < BoundaryAboveAll )BoundaryBelow minBound > BoundaryBelowAll:This is incorrect because there are no possible values in 8between the left and right sides of these inequalities. The boundary below all values. The boundary above all values. 5The argument is the lowest value above the boundary. 6The argument is the highest value below the boundary. EDistinguish between dense and sparse ordered types. A dense type is one in which any two values v1 < v2 have a third value v3 such that v1 < v3 < v2. PIn theory the floating types are dense, although in practice they can only have 8finitely many values. This class treats them as dense. NTuples up to 4 members are declared as instances. Larger tuples may be added if necessary. $Most values of sparse types have an  adjacentBelow, such that, for all x:   case adjacentBelow x of  Just x1 -> adjacent x1 x  Nothing -> True (The exception is for bounded types when x == lowerBound. For dense types  adjacentBelow always returns \. IThis approach was suggested by Ben Rudiak-Gould on comp.lang.functional.  Two values x and y are adjacent if x < y and there does not + exist a third value between them. Always False for dense types. CThe value immediately below the argument, if it can be determined. >Check adjacency for sparse enumerated types (i.e. where there  is no value between x and succ x). CCheck adjacency, allowing for case where x = maxBound. Use as the  definition of adjacent4 for bounded enumerated types such as Int and Char. The usual implementation of  for bounded enumerated types. :True if the value is above the boundary, false otherwise. Same as  ;, but with the arguments reversed for more intuitive infix  usage.      (A Range has upper and lower boundaries. 'True if the value is within the range. /True if the value is within one of the ranges. The empty range +The full range. All values are within it. "A range containing a single value %If the range is a singleton, returns Just the value. Otherwise returns  Nothing. Known bug: This always returns Nothing for ranges including  BoundaryBelowAll or BoundaryAboveAll". For bounded types this can be H incorrect. For instance, the following range only contains one value: 4 Range (BoundaryBelow maxBound) BoundaryAboveAll EA range is empty unless its upper boundary is greater than its lower  boundary. 5A range is full if it contains every possible value. 7Two ranges overlap if their intersection is non-empty. JThe first range encloses the second if every value in the second range is I also within the first range. If the second range is empty then this is  always true. $Intersection of two ranges, if any. 2Union of two ranges. Returns one or two results. FIf there are two results then they are guaranteed to have a non-empty 4 gap in between, but may not be in ascending order. range1 minus range2/. Returns zero, one or two results. Multiple M results are guaranteed to have non-empty gaps in between, but may not be in  ascending order. =The union of two ranges has a value iff either range has it.  prop_unionRange r1 r2 n = ) (r1 `rangeHas` n || r2 `rangeHas` n) - == (r1 `rangeUnion` r2) `rangeListHas` n ;The union of two ranges always contains one or two ranges. 4 prop_unionRangeLength r1 r2 = (n == 1) || (n == 2) ( where n = length $ rangeUnion r1 r2 DThe intersection of two ranges has a value iff both ranges have it. " prop_intersectionRange r1 r2 n = ) (r1 `rangeHas` n && r2 `rangeHas` n) 0 == (r1 `rangeIntersection` r2) `rangeHas` n !HThe difference of two ranges has a value iff the first range has it and  the second does not.  prop_differenceRange r1 r2 n = / (r1 `rangeHas` n && not (r2 `rangeHas` n)) 2 == (r1 `rangeDifference` r2) `rangeListHas` n "=Iff two ranges overlap then their intersection is non-empty. # prop_intersectionOverlap r1 r2 = F (rangeIsEmpty $ rangeIntersection r1 r2) == (rangeOverlap r1 r2) #2Range enclosure makes union an identity function.  prop_enclosureUnion r1 r2 = 6 rangeEncloses r1 r2 == (rangeUnion r1 r2 == [r1]) $ Range Singleton has its member. : prop_singletonRangeHas v = singletonRange v `rangeHas` v %%Range Singleton has only its member.  prop_singletonHasOnly v1 v2 = 4 (v1 == v2) == (singletonRange v1 `rangeHas` v2) &0A singleton range can have its value extracted. ! prop_singletonRangeConverse v = 5 rangeSingletonValue (singletonRange v) == Just v '$The empty range is not a singleton. D prop_emptyNonSingleton = rangeSingletonValue emptyRange == Nothing (#The full range is not a singleton. B prop_fullNonSingleton = rangeSingletonValue fullRange == Nothing )For real x and y, x < y* implies that any range between them is a  non-singleton. *JFor all integers x and y, any range formed from boundaries on either side @ of x and y is a singleton iff it contains exactly one integer.   !"#$%&'()*  !"#$%&'()*  !"#$%&'()*3+IAn RSet (for Ranged Set) is a list of ranges. The ranges must be sorted  and not overlap. ],-KDetermine if the ranges in the list are both in order and non-overlapping. F If so then they are suitable input for the unsafeRangedSet function. .IRearrange and merge the ranges in the list so that they are in order and  non-overlapping. ^/ECreate a new Ranged Set from a list of ranges. The list may contain 4 ranges that overlap or are not in ascending order. 0/Create a new Ranged Set from a list of ranges. validRangeList ranges  must return True%. This precondition is not checked. 1+Create a Ranged Set from a single element. 2 True if the set has no members. 30True if the negation of the set has no members. 45ITrue if the value is within the ranged set. Infix precedence is left 5. 67ETrue if the first argument is a subset of the second argument, or is  equal. Infix precedence is left 5. 89FTrue if the first argument is a strict subset of the second argument. Infix precedence is left 5. :;8Set union for ranged sets. Infix precedence is left 6. <=?Set intersection for ranged sets. Infix precedence is left 7. >?-Set difference. Infix precedence is left 6. @Set negation. AThe empty set. B"The set that contains everything. CConstruct a range set. A first lower boundary. BA function from a lower boundary to an upper boundary, which must : return a result greater than the argument (not checked). $A function from a lower boundary to Maybe the successor lower @ boundary, which must return a result greater than the argument = (not checked). If ranges overlap then they will be merged. D5A normalised range list is valid for unsafeRangedSet B prop_validNormalised ls = validRangeList $ normaliseRangeList ls E:Iff a value is in a range list then it is in a ranged set  constructed from that list. A prop_has ls v = (ls `rangeListHas` v) == makeRangedSet ls -?- v FBVerifies the correct membership of a set containing all integers  starting with the digit "1" up to 19999. H prop_unfold = (v <= 99999 && head (show v) == '1') == (initial1 -?- v)  where @ initial1 = rSetUnfold (BoundaryBelow 1) addNines times10 > addNines (BoundaryBelow n) = BoundaryAbove $ n * 2 - 1 $ times10 (BoundaryBelow n) = G if n <= 1000 then Just $ BoundaryBelow $ n * 10 else Nothing GGIff a value is in either of two ranged sets then it is in the union of  those two sets.  prop_union rs1 rs2 v = 7 (rs1 -?- v || rs2 -?- v) == ((rs1 -\/- rs2) -?- v) HHIff a value is in both of two ranged sets then it is n the intersection  of those two sets.  prop_intersection rs1 rs2 v = 7 (rs1 -?- v && rs2 -?- v) == ((rs1 -/\- rs2) -?- v) IIIff a value is in ranged set 1 and not in ranged set 2 then it is in the  difference of the two.  prop_difference rs1 rs2 v = < (rs1 -?- v && not (rs2 -?- v)) == ((rs1 -!- rs2) -?- v) J?Iff a value is not in a ranged set then it is in its negation. > prop_negation rs v = rs -?- v == not (rSetNegation rs -?- v) K)A set that contains a value is not empty ; prop_not_empty rs v = (rs -?- v) ==> not (rSetIsEmpty rs) LThe empty set has no members. & prop_empty v = not (rSetEmpty -?- v) MThe full set has every member.  prop_full v = rSetFull -?- v N6The intersection of a set with its negation is empty.  prop_empty_intersection rs = * rSetIsEmpty (rs -/\- rSetNegation rs) O.The union of a set with its negation is full.  prop_full_union rs v = ) rSetIsFull (rs -\/- rSetNegation rs) P:The union of two sets is the non-strict superset of both.  prop_union_superset rs1 rs2 =  rs1 -<=- u && rs2 -<=- u  where  u = rs1 -\/- rs2 Q?The intersection of two sets is the non-strict subset of both. $ prop_intersection_subset rs1 rs2 =  i -<=- rs1 && i -<=- rs2  where  i = rs1 -/\- rs2 RFThe difference of two sets intersected with the subtractand is empty.  prop_diff_intersect rs1 rs2 = ) rSetIsEmpty ((rs1 -!- rs2) -/\- rs2) S*A set is the non-strict subset of itself.  prop_subset rs = rs -<=- rs T*A set is not the strict subset of itself. ) prop_strict_subset rs = not (rs -<- rs) UIIf rs1 - rs2 is not empty then the union of rs1 and rs2 will be a strict  superset of rs2. & prop_union_strict_superset rs1 rs2 = & (not $ rSetIsEmpty (rs1 -!- rs2)) ! ==> (rs2 -<- (rs1 -\/- rs2)) VIntersection commutes. G prop_intersection_commutes rs1 rs2 = (rs1 -/\- rs2) == (rs2 -/\- rs1) WUnion commutes. @ prop_union_commutes rs1 rs2 = (rs1 -\/- rs2) == (rs2 -\/- rs1) XIntersection associates. , prop_intersection_associates rs1 rs2 rs3 = ; ((rs1 -/\- rs2) -/\- rs3) == (rs1 -/\- (rs2 -/\- rs3)) YUnion associates. % prop_union_associates rs1 rs2 rs3 = ; ((rs1 -\/- rs2) -\/- rs3) == (rs1 -\/- (rs2 -\/- rs3)) Z De Morgan's Law for Intersection. ' prop_de_morgan_intersection rs1 rs2 = L rSetNegation (rs1 -/\- rs2) == (rSetNegation rs1 -\/- rSetNegation rs2) [ De Morgan's Law for Union.  prop_de_morgan_union rs1 rs2 = L rSetNegation (rs1 -\/- rs2) == (rSetNegation rs1 -/\- rSetNegation rs2) 1+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[2+,,/0-.1C23547698;:=<?>@ABDEFGHIJKLMNOPQRSTUVWXYZ[1+,,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[_      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab/cdRanged-sets-0.2.0Data.Ranged.BoundariesData.Ranged.RangesData.Ranged.RangedSet Data.RangedBoundaryBoundaryBelowAllBoundaryAboveAll BoundaryBelow BoundaryAboveDiscreteOrderedadjacent adjacentBelow enumAdjacentboundedAdjacent boundedBelowabove/>/Range rangeLower rangeUpperrangeHas rangeListHas emptyRange fullRangesingletonRangerangeSingletonValue rangeIsEmpty rangeIsFull rangeOverlap rangeEnclosesrangeIntersection rangeUnionrangeDifferenceprop_unionRangeprop_unionRangeLengthprop_intersectionRangeprop_differenceRangeprop_intersectionOverlapprop_enclosureUnionprop_singletonRangeHasprop_singletonRangeHasOnlyprop_singletonRangeConverseprop_emptyNonSingletonprop_fullNonSingletonprop_nonSingletonprop_intSingletonRSet rSetRangesvalidRangeListnormaliseRangeList makeRangedSetunsafeRangedSet rSingleton rSetIsEmpty rSetIsFullrSetHas-?- rSetIsSubset-<=-rSetIsSubsetStrict-<- rSetUnion-\/-rSetIntersection-/\-rSetDifference-!- rSetNegation rSetEmptyrSetFull rSetUnfoldprop_validNormalisedprop_has prop_unfold prop_unionprop_intersectionprop_difference prop_negationprop_not_empty prop_empty prop_fullprop_empty_intersectionprop_full_unionprop_union_supersetprop_intersection_subsetprop_diff_intersect prop_subsetprop_strict_subsetprop_union_strict_supersetprop_intersection_commutesprop_union_commutesprop_intersection_associatesprop_union_associatesprop_de_morgan_intersectionprop_de_morgan_unionbase Data.MaybeNothing normalise