diff --git a/CHANGES.txt b/CHANGES.txt
new file mode 100644
--- /dev/null
+++ b/CHANGES.txt
@@ -0,0 +1,37 @@
+Version 0.0.4
+-------------
+
+Added Monoid instances and singleton ranges, courtesy of Jean-Philippe
+Bernardy.
+
+Version 0.0.3
+-------------
+
+Removed support for infinite sets.  They sometimes still work, but generally 
+are more trouble than they are worth.  There is no simple set of rules for
+client applications to guarantee termination.
+
+Replaced the "deriving" clause for the Range type with instance declarations.
+Empty ranges created with different bounds will now test as equal.  All
+empty ranges now compare as less than all non-empty ranges.  "show" returns
+a string such as "3.5 < x <= 4.6", or "x < 23".
+
+Removed "maybeRange".
+
+Changed "rangeIntersection" to return a "Range" instead of a "Maybe Range".
+If the intersection is empty then it returns an empty range instead of
+Nothing.
+
+Renamed "rangeEmpty" to "rangeIsEmpty" for consistency with "rSetIsEmpty"
+
+Added "emptyRange" and "fullRange"
+
+
+
+Version 0.0.2
+-------------
+
+Fixed the infinite loop with infinite sets, at least as far as possible.
+Added lots more QuickCheck properties.
+Added subset predicates.
+Added infix operators.
diff --git a/Data/Ranged.hs b/Data/Ranged.hs
new file mode 100644
--- /dev/null
+++ b/Data/Ranged.hs
@@ -0,0 +1,10 @@
+
+module Data.Ranged (
+   module Data.Ranged.Boundaries,
+   module Data.Ranged.Ranges,
+   module Data.Ranged.RangedSet
+) where
+
+import Data.Ranged.Boundaries
+import Data.Ranged.Ranges
+import Data.Ranged.RangedSet
diff --git a/Data/Ranged/Boundaries.hs b/Data/Ranged/Boundaries.hs
new file mode 100644
--- /dev/null
+++ b/Data/Ranged/Boundaries.hs
@@ -0,0 +1,170 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Ranged.Boundaries
+-- Copyright   :  (c) Paul Johnson 2006
+-- License     :  BSD-style
+-- Maintainer  :  paul@cogito.org.uk
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+
+
+
+module Data.Ranged.Boundaries (
+   DiscreteOrdered,
+   adjacent,
+   enumAdjacent,
+   boundedAdjacent,
+   Boundary (..),
+   above,
+   (/>/)
+) where
+
+import Data.Ratio
+import Test.QuickCheck
+
+infix 4 />/
+
+{- | 
+Distinguish 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@.
+
+In theory the floating types are dense, although in practice they can only have
+finitely many values.  This class treats them as dense.
+
+Tuples up to 4 members are declared as instances.  Larger tuples may be added
+if necessary.
+
+This approach was suggested by Ben Rudiak-Gould on comp.lang.functional.
+-}
+class Ord a => DiscreteOrdered a where
+   -- | 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.
+   adjacent :: a -> a -> Bool
+
+instance DiscreteOrdered Bool         where adjacent = boundedAdjacent
+instance DiscreteOrdered Ordering     where adjacent = boundedAdjacent
+instance DiscreteOrdered Char         where adjacent = boundedAdjacent
+instance DiscreteOrdered Int          where adjacent = boundedAdjacent
+instance DiscreteOrdered Integer      where adjacent = enumAdjacent
+instance Integral a => DiscreteOrdered (Ratio a)
+                                      where adjacent _ _ = False
+instance DiscreteOrdered Float        where adjacent _ _ = False
+instance DiscreteOrdered Double       where adjacent _ _ = False
+instance Ord a => DiscreteOrdered [a] where adjacent _ _ = False
+instance (Ord a, DiscreteOrdered b) => DiscreteOrdered (a, b)
+   where adjacent (x1, x2) (y1, y2) = (x1 == y1) && adjacent x2 y2
+instance (Ord a, Ord b, DiscreteOrdered c) => DiscreteOrdered (a, b, c)
+   where 
+      adjacent (x1, x2, x3) (y1, y2, y3) =
+         (x1 == y1) && (x2 == y2) && adjacent x3 y3
+instance (Ord a, Ord b, Ord c, DiscreteOrdered d) => 
+         DiscreteOrdered (a, b, c, d)
+   where 
+      adjacent (x1, x2, x3, x4) (y1, y2, y3, y4) =
+         (x1 == y1) && (x2 == y2) && (x3 == y3) && adjacent x4 y4
+ 
+-- | Check adjacency for sparse enumerated types (i.e. where there
+-- is no value between @x@ and @succ x@).  Use as the definition of
+-- "adjacent" for most enumerated types.
+enumAdjacent :: (Ord a, Enum a) => a -> a -> Bool
+enumAdjacent x y = (succ x == y)    
+         
+-- | Check adjacency, allowing for case where x = maxBound.  Use as the
+-- definition of "adjacent" for bounded enumerated types such as Int and Char.
+boundedAdjacent :: (Ord a, Enum a) => a -> a -> Bool
+boundedAdjacent x y = if x < y then succ x == y else False
+   
+     
+{- |
+A Boundary is a division of an ordered type into values above 
+and 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 
+between the left and right sides of these inequalities. 
+-}
+
+data Boundary a =
+      -- | The argument is the highest value below the boundary.
+      BoundaryAbove a | 
+      -- | The argument is the lowest value above the boundary.
+      BoundaryBelow a |
+      -- | The boundary above all values.
+      BoundaryAboveAll | 
+      -- | The boundary below all values.
+      BoundaryBelowAll
+   deriving (Show)
+
+-- | True if the value is above the boundary, false otherwise.
+above :: Ord v => Boundary v -> v -> Bool
+above (BoundaryAbove b) v    = v > b
+above (BoundaryBelow b) v    = v >= b
+above BoundaryAboveAll _     = False
+above BoundaryBelowAll _     = True
+   
+-- | Same as 'above', but with the arguments reversed for more intuitive infix
+-- usage.   
+(/>/) :: Ord v => v -> Boundary v -> Bool
+(/>/) = flip above
+   
+instance (DiscreteOrdered a) => Eq (Boundary a) where
+   b1 == b2  = compare b1 b2 == EQ
+
+instance (DiscreteOrdered a) => Ord (Boundary a) where
+   -- Comparison alogrithm based on brute force and ignorance: 
+   -- enumerate all combinations.
+   
+   compare boundary1 boundary2 =
+      case boundary1 of
+         BoundaryAbove b1 ->
+            case boundary2 of
+               BoundaryAbove b2 -> compare b1 b2
+               BoundaryBelow b2 -> 
+                  if b1 < b2 
+                     then 
+                        if adjacent b1 b2 then EQ else LT 
+                     else GT
+               BoundaryAboveAll -> LT
+               BoundaryBelowAll -> GT
+         BoundaryBelow b1 ->
+            case boundary2 of
+               BoundaryAbove b2 -> 
+                  if b1 > b2 
+                     then 
+                        if adjacent b2 b1 then EQ else GT 
+                     else LT
+               BoundaryBelow b2 -> compare b1 b2
+               BoundaryAboveAll -> LT
+               BoundaryBelowAll -> GT
+         BoundaryAboveAll ->
+            case boundary2 of
+               BoundaryAboveAll -> EQ
+               otherwise        -> GT
+         BoundaryBelowAll ->
+            case boundary2 of
+               BoundaryBelowAll -> EQ
+               otherwise        -> LT
+
+-- QuickCheck Generator
+
+instance Arbitrary a => Arbitrary (Boundary a) where
+   arbitrary = frequency [
+      (1, return BoundaryAboveAll),
+      (1, return BoundaryBelowAll),
+      (18, do
+         v <- arbitrary
+         oneof [return $ BoundaryAbove v, return $ BoundaryBelow v]
+      )]
+   coarbitrary BoundaryBelowAll   = variant 0   
+   coarbitrary BoundaryAboveAll   = variant 1
+   coarbitrary (BoundaryBelow v)  = variant 2 . coarbitrary v
+   coarbitrary (BoundaryAbove v)  = variant 3 . coarbitrary v
+
diff --git a/Data/Ranged/RangedSet.hs b/Data/Ranged/RangedSet.hs
new file mode 100644
--- /dev/null
+++ b/Data/Ranged/RangedSet.hs
@@ -0,0 +1,539 @@
+module Data.Ranged.RangedSet ( 
+   -- ** Ranged Set Type
+   RSet,
+   rSetRanges,
+   -- ** Ranged Set construction functions and their Preconditions
+   makeRangedSet,
+   unsafeRangedSet,
+   validRangeList,
+   normaliseRangeList,
+   rSingleton,
+   -- ** Predicates
+   rSetIsEmpty,
+   (-?-),  rSetHas, 
+   (-<=-), rSetIsSubset,
+   (-<-),  rSetIsSubsetStrict,
+   -- ** Set Operations
+   (-\/-), rSetUnion, 
+   (-/\-), rSetIntersection, 
+   (-!-),  rSetDifference,
+   rSetNegation,
+   -- ** Useful Sets
+   rSetEmpty,
+   rSetFull,
+   rSetUnfold
+   
+   -- ** QuickCheck Properties
+   
+   -- *** Construction
+   -- $ConstructionProperties
+   
+   -- *** Basic Operations
+   -- $BasicOperationProperties
+   
+   -- *** Some Identities and Inequalities
+   -- $SomeIdentitiesAndInequalities
+) where
+
+import Data.Ranged.Boundaries
+import Data.Ranged.Ranges
+import Data.Monoid
+
+import Data.List
+import Test.QuickCheck
+
+infixl 7 -/\-
+infixl 6 -\/-, -!-
+infixl 5 -<=-, -<-, -?-
+
+-- | An RSet (for Ranged Set) is a list of ranges.  The ranges must be sorted
+-- and not overlap.
+
+newtype DiscreteOrdered v => RSet v = RSet {rSetRanges :: [Range v]}
+   deriving (Eq, Show)
+
+instance DiscreteOrdered a => Monoid (RSet a) where
+    mappend = rSetUnion
+    mempty = rSetEmpty
+
+-- | Determine if the ranges in the list are both in order and non-overlapping.
+-- If so then they are suitable input for the unsafeRangedSet function.
+validRangeList :: DiscreteOrdered v => [Range v] -> Bool
+
+validRangeList [] = True
+validRangeList [Range lower upper] = lower <= upper
+validRangeList ranges = and $ zipWith okAdjacent ranges (tail ranges)
+   where
+      okAdjacent (Range lower1 upper1) (Range lower2 upper2) =
+         lower1 <= upper1 && upper1 <= lower2 && lower2 <= upper2
+
+
+-- | Rearrange and merge the ranges in the list so that they are in order and
+-- non-overlapping.
+normaliseRangeList :: DiscreteOrdered v => [Range v] -> [Range v]
+   
+normaliseRangeList ranges = 
+   normalise $ sort $ filter (not . rangeIsEmpty) ranges
+      
+
+-- Private routine: normalise a range list that is known to be already sorted.
+-- This precondition is not checked.
+normalise :: DiscreteOrdered v => [Range v] -> [Range v]
+normalise (r1:r2:rs) =
+         if overlap r1 r2  
+               then normalise $
+                       Range (rangeLower r1) 
+                             (max (rangeUpper r1) (rangeUpper r2))
+                       : rs
+               else r1 : (normalise $ r2 : rs)
+   where
+      overlap (Range _ upper1) (Range lower2 _) = upper1 >= lower2
+      
+normalise rs = rs
+
+
+-- | Create a new Ranged Set from a list of ranges.  The list may contain
+-- ranges that overlap or are not in ascending order.
+makeRangedSet :: DiscreteOrdered v => [Range v] -> RSet v
+makeRangedSet = RSet . normaliseRangeList
+
+
+-- | Create a new Ranged Set from a list of ranges. @validRangeList ranges@ 
+-- must return @True@.  This precondition is not checked.
+unsafeRangedSet :: DiscreteOrdered v => [Range v] -> RSet v
+unsafeRangedSet = RSet
+
+-- | Create a Ranged Set from a single element.
+rSingleton :: DiscreteOrdered v => v -> RSet v
+rSingleton v = unsafeRangedSet [singletonRange v]
+
+-- | True if the set has no members.
+rSetIsEmpty :: DiscreteOrdered v => RSet v -> Bool
+rSetIsEmpty = null . rSetRanges
+
+
+-- | True if the negation of the set has no members.
+rSetIsFull :: DiscreteOrdered v => RSet v -> Bool
+rSetIsFull = rSetIsEmpty . rSetNegation
+
+
+-- | True if the value is within the ranged set.  Infix precedence is left 5.
+rSetHas, (-?-) :: DiscreteOrdered v => RSet v -> v -> Bool
+rSetHas (RSet ls) value = rSetHas1 ls
+   where
+      rSetHas1 [] = False
+      rSetHas1 (r:rs)
+         | value />/ rangeLower r = rangeHas r value || rSetHas1 rs
+         | otherwise              = False
+
+(-?-) = rSetHas
+
+-- | True if the first argument is a subset of the second argument, or is 
+-- equal. 
+-- 
+-- Infix precedence is left 5.
+rSetIsSubset, (-<=-) :: DiscreteOrdered v => RSet v -> RSet v -> Bool
+rSetIsSubset rs1 rs2 = rSetIsEmpty (rs1 -!- rs2)
+(-<=-) = rSetIsSubset
+
+
+-- | True if the first argument is a strict subset of the second argument.
+-- 
+-- Infix precedence is left 5.
+rSetIsSubsetStrict, (-<-) :: DiscreteOrdered v => RSet v -> RSet v -> Bool
+rSetIsSubsetStrict rs1 rs2 = 
+   rSetIsEmpty (rs1 -!- rs2) 
+   && not (rSetIsEmpty (rs2 -!- rs1))
+   
+(-<-) = rSetIsSubsetStrict
+
+-- | Set union for ranged sets.  Infix precedence is left 6.
+rSetUnion, (-\/-) :: DiscreteOrdered v => RSet v -> RSet v -> RSet v
+-- Implementation note: rSetUnion merges the two lists into a single
+-- sorted list and then calls normalise to combine overlapping ranges.
+rSetUnion (RSet ls1) (RSet ls2) = RSet $ normalise $ merge ls1 ls2
+   where
+      merge ls1 [] = ls1
+      merge [] ls2 = ls2
+      merge ls1@(h1:t1) ls2@(h2:t2) =
+         if h1 <  h2
+            then h1 : merge t1 ls2
+            else h2 : merge ls1 t2
+
+(-\/-) = rSetUnion
+
+-- | Set intersection for ranged sets.  Infix precedence is left 7.
+rSetIntersection, (-/\-) :: DiscreteOrdered v => RSet v -> RSet v -> RSet v
+rSetIntersection (RSet ls1) (RSet ls2) =  
+   RSet $ filter (not . rangeIsEmpty) $ merge ls1 ls2
+   where
+      merge ls1@(h1:t1) ls2@(h2:t2) =
+         rangeIntersection h1 h2 
+         : if rangeUpper h1 < rangeUpper h2
+               then merge t1 ls2
+               else merge ls1 t2
+      merge _ _ = []
+
+(-/\-) = rSetIntersection
+
+
+-- | Set difference.  Infix precedence is left 6.
+rSetDifference, (-!-) :: DiscreteOrdered v => RSet v -> RSet v -> RSet v
+rSetDifference rs1 rs2 = rs1 -/\- (rSetNegation rs2)
+(-!-) = rSetDifference
+
+
+-- | Set negation.
+rSetNegation :: DiscreteOrdered a => RSet a -> RSet a
+rSetNegation set = RSet $ ranges $ setBounds1
+   where
+      ranges (b1:b2:bs) = Range b1 b2 : ranges bs
+      ranges [BoundaryAboveAll] = []
+      ranges [b] = [Range b BoundaryAboveAll]
+      ranges _ = []
+      setBounds1 = case setBounds of
+         (BoundaryBelowAll : bs)  -> bs
+         _                        -> BoundaryBelowAll : setBounds
+      setBounds = bounds $ rSetRanges set 
+      bounds (r:rs) = rangeLower r : rangeUpper r : bounds rs
+      bounds _ = []
+
+
+-- | The empty set.
+rSetEmpty :: DiscreteOrdered a => RSet a
+rSetEmpty = RSet []
+
+-- | The set that contains everything.
+rSetFull :: DiscreteOrdered a => RSet a
+rSetFull = RSet [Range BoundaryBelowAll BoundaryAboveAll]
+
+
+-- | Construct a range set.
+rSetUnfold :: DiscreteOrdered a => 
+   Boundary a
+      -- ^ A first lower boundary.
+   -> (Boundary a -> Boundary a) 
+      -- ^ A function from a lower boundary to an upper boundary, which must
+      -- return a result greater than the argument (not checked).
+   -> (Boundary a -> Maybe (Boundary a))
+      -- ^ A function from a lower boundary to @Maybe@ the successor lower 
+      -- boundary, which must return a result greater than the argument 
+      -- (not checked).
+   -> RSet a
+rSetUnfold bound upperFunc succFunc = RSet $ normalise $ ranges bound
+   where
+      ranges b = 
+         Range b (upperFunc bound)
+         : case succFunc b of
+            Just b2 -> ranges b2
+            Nothing -> []
+   
+   
+-- QuickCheck Generators
+
+instance (Arbitrary v, DiscreteOrdered v, Show v) => 
+      Arbitrary (RSet v) 
+   where
+   arbitrary = frequency [
+      (1, return rSetEmpty),
+      (1, return rSetFull),
+      (18, do
+         ls <- arbitrary
+         return $ makeRangedSet $ rangeList $ sort ls
+      )]
+      where
+         -- Arbitrary lists of ranges don't give many interesting sets after
+         -- normalisation.  So instead generate a sorted list of boundaries
+         -- and pair them off.  Odd boundaries are dropped.
+         rangeList (b1:b2:bs) = Range b1 b2 : rangeList bs
+         rangeList _ = []
+      
+   coarbitrary (RSet ls) = variant 0 . coarbitrary ls
+
+-- ==================================================================  
+-- QuickCheck Properties
+-- ==================================================================
+
+-- Note for maintenance: Haddock does not include QuickCheck properties,
+-- so they have to be copied into documentation blocks manually.  This
+-- process must be repeated for new or modified properties.
+
+
+---------------------------------------------------------------------
+-- Construction properties
+---------------------------------------------------------------------
+
+{- $ConstructionProperties
+
+A normalised range list is valid for unsafeRangedSet
+
+> prop_validNormalised ls = validRangeList $ normaliseRangeList ls
+>    where types = ls :: [Range Double]
+
+Iff a value is in a range list then it is in a ranged set
+constructed from that list.
+
+> prop_has ls v = (ls `rangeListHas` v) == rangedSet ls -?- v
+
+-}
+
+-- A normalised range list is valid for unsafeRangedSet
+prop_validNormalised ls = validRangeList $ normaliseRangeList ls
+   where types = ls :: [Range Integer]
+
+-- Iff a value is in a range list then it is in a ranged set
+-- constructed from that list.
+prop_has ls v = (ls `rangeListHas` v) == makeRangedSet ls -?- v
+   where types = v :: Integer
+
+---------------------------------------------------------------------
+-- Basic operation properties
+---------------------------------------------------------------------
+
+{- $BasicOperationProperties
+Iff a value is in either of two ranged sets then it is in the union of
+those two sets.
+
+> prop_union rs1 rs2 v =
+>    (rs1 -?- v || rs2 -?- v) == ((rs1 -\/- rs2) -?- v)
+
+Iff a value is in both of two ranged sets then it is in the intersection
+of those two sets.
+
+> prop_intersection rs1 rs2 v =
+>    (rs1 -?- v && rs2 -?- v) == ((rs1 -/\- rs2) -?- v)
+
+      
+Iff 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)
+
+
+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)
+
+
+A set that contains a value is not empty
+
+> prop_not_empty rs v = (rs -?- v) ==> not (rSetIsEmpty rs)
+
+-}     
+ 
+-- Iff a value is in either of two ranged sets then it is in the union of
+-- those two sets.
+prop_union rs1 rs2 v = (rs1 -?- v || rs2 -?- v) == ((rs1 -\/- rs2) -?- v)
+   where types = v :: Integer
+
+-- Iff a value is in both of two ranged sets then it is in the intersection
+-- of those two sets.
+prop_intersection rs1 rs2 v = 
+   (rs1 -?- v && rs2 -?- v) == ((rs1 `rSetIntersection` rs2) -?- v)
+   where types = v :: Integer
+
+      
+-- Iff 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)
+   where types = v :: Integer
+
+
+-- 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)
+   where types = v :: Integer
+
+
+-- A set that contains a value is not empty
+prop_not_empty rs v = (rs -?- v) ==> not (rSetIsEmpty rs)
+   where types = v :: Integer
+   
+
+---------------------------------------------------------------------
+-- Some identities and inequalities of sets
+---------------------------------------------------------------------
+
+{- $SomeIdentitiesAndInequalities
+
+The empty set has no members.
+
+> prop_empty v = not (rSetEmpty -?- v)
+
+
+The full set has every member.
+
+> prop_full v = rSetFull -?- v
+
+
+The intersection of a set with its negation is empty.
+
+> prop_empty_intersection rs =
+>    rSetIsEmpty (rs -/\- rSetNegation rs) 
+   
+   
+The union of a set with its negation is full.
+
+> prop_full_union rs v =
+>    rSetIsFull (rs -\/- rSetNegation rs)
+
+
+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
+      
+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
+
+The difference of two sets intersected with the subtractand is empty.
+
+> prop_diff_intersect rs1 rs2 =
+>    rSetIsEmpty ((rs1 -!- rs2) -/\- rs2)
+
+A set is the non-strict subset of itself.
+
+> prop_subset rs = rs -<=- rs
+
+   
+A set is not the strict subset of itself.
+
+> prop_strict_subset rs = not (rs -<- rs)
+   
+
+If 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))
+
+Intersection commutes
+
+> prop_intersection_commutes rs1 rs2 =
+>    (rs1 -/\- rs2) == (rs2 -/\- rs1)
+   
+Union commutes
+
+> prop_union_commutes rs1 rs2 =
+>    (rs1 -\/- rs2) == (rs2 -\/- rs1)
+   
+Intersection associates
+
+> prop_intersection_associates rs1 rs2 rs3 =
+>    ((rs1 -/\- rs2) -/\- rs3) == (rs1 -/\- (rs2 -/\- rs3))
+  
+Union associates
+
+> prop_union_associates rs1 rs2 rs3 =
+>    ((rs1 -\/- rs2) -\/- rs3) == (rs1 -\/- (rs2 -\/- rs3))
+
+De Morgan's Law for Intersection
+
+> prop_de_morgan_intersection rs1 rs2 =
+>    rSetNegation (rs1 -/\- rs2) == (rSetNegation rs1 -\/- rSetNegation rs2)
+
+De Morgan's Law for Union
+
+> prop_de_morgan_union rs1 rs2 =
+>    rSetNegation (rs1 -\/- rs2) == (rSetNegation rs1 -/\- rSetNegation rs2)
+
+-}
+
+-- The empty set has no members.
+prop_empty v = not (rSetEmpty -?- v)
+   where types = v :: Integer
+
+
+-- The full set has every member.
+prop_full v = rSetFull -?- v
+   where types = v :: Integer
+
+
+-- The intersection of a set with its negation is empty.
+prop_empty_intersection rs =
+   rSetIsEmpty (rs -/\- rSetNegation rs) 
+   where types = rs :: RSet Integer
+   
+   
+-- The union of a set with its negation is full.
+prop_full_union rs =
+   rSetIsFull (rs -\/- rSetNegation rs)
+   where types = rs :: RSet Integer
+
+
+-- The union of two sets is the non-strict superset of both.
+prop_union_superset rs1 rs2 =
+   rs1 -<=- u && rs2 -<=- u 
+   where
+      u :: RSet Integer
+      u = rs1 -\/- rs2
+      
+-- The intersection of two sets is the non-strict subset of both.
+prop_intersection_subset rs1 rs2 =
+   i -<=- rs1 && i -<=- rs2
+   where
+      i :: RSet Integer
+      i = rs1 -/\- rs2
+
+-- The difference of two sets intersected with the subtractand is empty.
+prop_diff_intersect rs1 rs2 =
+   rSetIsEmpty ((rs1 -!- rs2) -/\- rs2)
+   where types = rs1 :: RSet Integer
+   
+   
+-- A set is the non-strict subset of itself.
+prop_subset rs =
+   rs -<=- rs
+   where types = rs :: RSet Integer
+   
+-- A set is not the strict subset of itself.
+prop_strict_subset rs =
+   not (rs -<- rs)
+   where types = rs :: RSet Integer
+   
+
+-- If 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))
+   where types = rs1 :: RSet Integer
+
+-- Intersection commutes
+prop_intersection_commutes :: RSet Integer -> RSet Integer -> Bool
+prop_intersection_commutes rs1 rs2 =
+   (rs1 -/\- rs2) == (rs2 -/\- rs1)
+   where types = rs1 :: RSet Integer
+   
+-- Union commutes
+prop_union_commutes rs1 rs2 =
+   (rs1 -\/- rs2) == (rs2 -\/- rs1)
+   where types = rs1 :: RSet Integer
+   
+-- Intersection associates
+prop_intersection_associates rs1 rs2 rs3 =
+   ((rs1 -/\- rs2) -/\- rs3) == (rs1 -/\- (rs2 -/\- rs3))
+   where types = rs1 :: RSet Integer
+   
+-- Union associates
+prop_union_associates rs1 rs2 rs3 =
+   ((rs1 -\/- rs2) -\/- rs3) == (rs1 -\/- (rs2 -\/- rs3))
+   where types = rs1 :: RSet Integer
+   
+-- De Morgan's Law for Intersection
+prop_de_morgan_intersection rs1 rs2 =
+   rSetNegation (rs1 -/\- rs2) == (rSetNegation rs1 -\/- rSetNegation rs2)
+   where types = rs1 :: RSet Integer
+
+-- De Morgan's Law for Union
+prop_de_morgan_union rs1 rs2 =
+   rSetNegation (rs1 -\/- rs2) == (rSetNegation rs1 -/\- rSetNegation rs2)
+   where types = rs1 :: RSet Integer
diff --git a/Data/Ranged/Ranges.hs b/Data/Ranged/Ranges.hs
new file mode 100644
--- /dev/null
+++ b/Data/Ranged/Ranges.hs
@@ -0,0 +1,294 @@
+-----------------------------------------------------------------------------
+-- 
+-- Module      :  Data.Ranged.Ranges
+-- Copyright   :  (c) Paul Johnson 2006
+-- License     :  BSD-style
+-- Maintainer  :  paul@cogito.org.uk
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+
+
+-- | A range has an upper and lower boundary.
+
+module Data.Ranged.Ranges (
+   -- ** Construction
+   Range (..),
+   emptyRange,
+   fullRange,
+   -- ** Predicates
+   rangeIsEmpty,
+   rangeOverlap,
+   rangeEncloses,
+   rangeSingletonValue,
+   -- ** Membership
+   rangeHas,
+   rangeListHas,
+   -- ** Set Operations
+   singletonRange,
+   rangeIntersection,
+   rangeUnion,
+   rangeDifference
+   -- ** QuickCheck properties
+   -- $properties
+) where
+
+import Data.Ranged.Boundaries
+import Data.Maybe
+import Test.QuickCheck
+
+-- | A Range has upper and lower boundaries.
+data Ord v => Range v = Range {rangeLower, rangeUpper :: Boundary v}
+
+instance (DiscreteOrdered a) => Eq (Range a) where
+   r1 == r2   = (rangeIsEmpty r1 && rangeIsEmpty r2) || 
+                (rangeLower r1 == rangeLower r2 && 
+                 rangeUpper r1 == rangeUpper r2)
+
+
+instance (DiscreteOrdered a) => Ord (Range a) where
+   compare r1 r2
+      | r1 == r2       = EQ
+      | rangeIsEmpty r1  = LT
+      | rangeIsEmpty r2  = GT
+      | otherwise      = compare (rangeLower r1, rangeUpper r1)
+                                 (rangeLower r2, rangeUpper r2)
+                                 
+instance (Show a, DiscreteOrdered a) => Show (Range a) where
+   show r
+      | rangeIsEmpty r     = "Empty"
+      | otherwise          = 
+         case rangeSingletonValue r of
+            Just v  -> "x == " ++ show v
+            Nothing -> lowerBound ++ "x" ++ upperBound
+      where
+         lowerBound = case rangeLower r of
+            BoundaryBelowAll -> ""
+            BoundaryBelow v  -> show v ++ " <= "
+            BoundaryAbove v  -> show v ++ " < "
+            BoundaryAboveAll -> error "show Range: lower bound is BoundaryAboveAll"
+         upperBound = case rangeUpper r of
+            BoundaryBelowAll -> error "show Range: upper bound is BoundaryBelowAll"
+            BoundaryBelow v  -> " < " ++ show v
+            BoundaryAbove v  -> " <= " ++ show v
+            BoundaryAboveAll -> ""
+
+
+-- | True if the value is within the range.
+rangeHas :: Ord v => Range v -> v -> Bool
+
+rangeHas (Range b1 b2) v =
+   (v />/ b1) && not (v />/ b2)
+
+
+-- | True if the value is within one of the ranges.
+rangeListHas :: Ord v =>
+   [Range v] -> v -> Bool
+rangeListHas ls v = or $ map (\r -> rangeHas r v) ls
+
+-- | The empty range
+emptyRange :: DiscreteOrdered v => Range v
+emptyRange = Range BoundaryAboveAll BoundaryBelowAll
+
+-- | The full range.  All values are within it.
+fullRange :: DiscreteOrdered v => Range v
+fullRange = Range BoundaryBelowAll BoundaryAboveAll
+
+-- | A range containing a single value
+singletonRange :: DiscreteOrdered v => v -> Range v
+singletonRange v = Range (BoundaryBelow v) (BoundaryAbove v)
+
+-- | If the range is a singleton, returns @Just@ the value.  Otherwise returns
+-- @Nothing@.
+rangeSingletonValue :: DiscreteOrdered v => Range v -> Maybe v
+rangeSingletonValue (Range (BoundaryBelow v1) (BoundaryAbove v2))
+   | v1 == v2    = Just v1
+   | otherwise   = Nothing
+rangeSingletonValue _ = Nothing
+
+-- | A range is empty unless its upper boundary is greater than its lower
+-- boundary.
+rangeIsEmpty :: DiscreteOrdered v => Range v -> Bool
+rangeIsEmpty (Range lower upper) = upper <= lower
+
+
+-- | Two ranges overlap if their intersection is non-empty.
+rangeOverlap :: DiscreteOrdered v => Range v -> Range v -> Bool
+rangeOverlap r1 r2 = 
+   not (rangeIsEmpty r1)
+   && not (rangeIsEmpty r2)
+   && not (rangeUpper r1 <= rangeLower r2 || rangeUpper r2 <= rangeLower r1)
+ 
+  
+-- | The first range encloses the second if every value in the second range is 
+-- also within the first range.  If the second range is empty then this is
+-- always true.
+rangeEncloses :: DiscreteOrdered v => Range v -> Range v -> Bool
+rangeEncloses r1 r2 =
+   (rangeLower r1 <= rangeLower r2 && rangeUpper r2 <= rangeUpper r1) 
+   || rangeIsEmpty r2
+
+
+-- | Intersection of two ranges, if any.
+rangeIntersection :: DiscreteOrdered v => Range v -> Range v -> Range v
+   
+rangeIntersection (Range lower1 upper1) (Range lower2 upper2) =
+   Range (max lower1 lower2) (min upper1 upper2)
+     
+     
+-- | Union of two ranges.  Returns one or two results.
+--
+-- If there are two results then they are guaranteed to have a non-empty
+-- gap in between, but may not be in ascending order.
+rangeUnion :: DiscreteOrdered v => Range v -> Range v -> [Range v]
+   
+rangeUnion r1@(Range lower1 upper1) r2@(Range lower2 upper2) =
+   if touching
+      then [Range lower upper]
+      else [r1, r2]
+   where
+      touching = (max lower1 lower2) <= (min upper1 upper2)
+      lower = min lower1 lower2
+      upper = max upper1 upper2
+
+
+-- | @range1@ minus @range2@.  Returns zero, one or two results.  Multiple 
+-- results are guaranteed to have non-empty gaps in between, but may not be in 
+-- ascending order.
+rangeDifference :: DiscreteOrdered v => Range v -> Range v -> [Range v]
+   
+rangeDifference r1@(Range lower1 upper1) r2@(Range lower2 upper2) =
+   -- There are six possibilities
+   --    1: r2 completely less than r1
+   --    2: r2 overlaps bottom of r1
+   --    3: r2 encloses r1
+   --    4: r1 encloses r2
+   --    5: r2 overlaps top of r1
+   --    6: r2 completely greater than r1
+   if intersects
+      then -- Cases 2,3,4,5
+         filter (not . rangeIsEmpty) [Range lower1 lower2, Range upper2 upper1]
+      else -- Cases 1, 6
+         [r1]
+   where
+      intersects = (max lower1 lower2) < (min upper1 upper2)
+
+
+-- QuickCheck generators
+
+instance (Arbitrary v,  DiscreteOrdered v, Show v) => 
+   Arbitrary (Range v) where
+   
+   arbitrary = frequency [
+      (17, do  -- Ordinary range
+         b1 <- arbitrary
+         b2 <- arbitrary
+         if b1 < b2 
+            then return $ Range b1 b2
+            else return $ Range b2 b1
+      ),
+      (1, do  -- Singleton range
+         v <- arbitrary
+         return $ singletonRange v
+      ),
+      (1, return emptyRange),
+      (1, return fullRange)
+      ]
+      
+   coarbitrary (Range lower upper) =
+      variant 0 . coarbitrary lower . coarbitrary upper
+      
+
+         
+-- QuickCheck Properties
+
+{- $properties
+Range union
+
+> prop_union r1 r2 n =
+>    (r1 `rangeHas` n || r2 `rangeHas` n) 
+>    == (r1 `rangeUnion` r2) `rangeListHas` n
+
+Range intersection
+
+> prop_intersection r1 r2 n =
+>    (r1 `rangeHas` n && r2 `rangeHas` n)
+>    == (r1 `rangeIntersection` r2) `rangeHas` n
+
+Range difference
+
+> prop_difference r1 r2 n =
+>    (r1 `rangeHas` n && not (r2 `rangeHas` n))
+>    == (r1 `rangeDifference` r2) `rangeListHas` n
+
+Singleton range
+
+> prop_singletonHas v =
+>    singletonRange v `rangeHas` v
+
+> prop_singletonConverse v =
+>    rangeSingletonValue (singletonRange v) == Just v
+
+-}
+
+-- For Integers (sparse type)
+
+-- Range union
+prop_union_int r1 r2 n = 
+   (r1 `rangeHas` n || r2 `rangeHas` n) 
+   == (r1 `rangeUnion` r2) `rangeListHas` n
+   where t :: Integer ; t = n
+
+
+-- Range intersection
+prop_intersection_int r1 r2 n =
+   (r1 `rangeHas` n && r2 `rangeHas` n)
+   == (r1 `rangeIntersection` r2) `rangeHas` n
+   where t :: Integer ; t = n
+
+-- Range difference
+prop_difference_int r1 r2 n =
+   (r1 `rangeHas` n && not (r2 `rangeHas` n))
+   == (r1 `rangeDifference` r2) `rangeListHas` n
+   where t :: Integer ; t = n
+
+-- Range Singleton Has
+prop_singletonHas_int v =
+   singletonRange v `rangeHas` v
+   where t :: Integer ; t = v
+
+-- Range Singleton inverse
+prop_singletonConverse_int v =
+   rangeSingletonValue (singletonRange v) == Just v
+   where t :: Integer ; t = v
+
+-- For Reals (dense type)
+
+-- Range Union
+prop_union_real r1 r2 n = 
+   (r1 `rangeHas` n || r2 `rangeHas` n) 
+   == (r1 `rangeUnion` r2) `rangeListHas` n
+   where t :: Double ; t = n
+
+-- Range intersection
+prop_intersection_real r1 r2 n =
+   (r1 `rangeHas` n && r2 `rangeHas` n)
+   == (r1 `rangeIntersection` r2) `rangeHas` n
+   where t :: Double ; t = n
+
+-- Range difference
+prop_difference_real r1 r2 n =
+   (r1 `rangeHas` n && not (r2 `rangeHas` n))
+   == (r1 `rangeDifference` r2) `rangeListHas` n
+   where t :: Double ; t = n
+
+-- Range Singleton Has
+prop_singletonHas_real v =
+   singletonRange v `rangeHas` v
+   where t :: Double ; t = v
+
+-- Range Singleton inverse
+prop_singletonConverse_real v =
+   rangeSingletonValue (singletonRange v) == Just v
+   where t :: Double ; t = v
diff --git a/Doc/Data-Ranged-Boundaries.html b/Doc/Data-Ranged-Boundaries.html
new file mode 100644
--- /dev/null
+++ b/Doc/Data-Ranged-Boundaries.html
@@ -0,0 +1,681 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--Rendered using the Haskell Html Library v0.2-->
+<HTML
+><HEAD
+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"
+><TITLE
+>Data.Ranged.Boundaries</TITLE
+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"
+><SCRIPT SRC="haddock.js" TYPE="text/javascript"
+></SCRIPT
+></HEAD
+><BODY
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="topbar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "
+></TD
+><TD CLASS="title"
+></TD
+><TD CLASS="topbut"
+><A HREF="index.html"
+>Contents</A
+></TD
+><TD CLASS="topbut"
+><A HREF="doc-index.html"
+>Index</A
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="modulebar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><FONT SIZE="6"
+>Data.Ranged.Boundaries</FONT
+></TD
+><TD ALIGN="right"
+><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="infohead"
+>Portability</TD
+><TD CLASS="infoval"
+>portable</TD
+></TR
+><TR
+><TD CLASS="infohead"
+>Stability</TD
+><TD CLASS="infoval"
+>experimental</TD
+></TR
+><TR
+><TD CLASS="infohead"
+>Maintainer</TD
+><TD CLASS="infoval"
+>paul@cogito.org.uk</TD
+></TR
+></TABLE
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section1"
+>Description</TD
+></TR
+><TR
+><TD CLASS="doc"
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section1"
+>Synopsis</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+><SPAN CLASS="keyword"
+>class</SPAN
+> Ord a =&gt; <A HREF="#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a  <SPAN CLASS="keyword"
+>where</SPAN
+></TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3Aadjacent"
+>adjacent</A
+> :: a -&gt; a -&gt; Bool</TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3Aadjacent"
+>adjacent</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; a -&gt; a -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3AenumAdjacent"
+>enumAdjacent</A
+> :: (Ord a, Enum a) =&gt; a -&gt; a -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3AboundedAdjacent"
+>boundedAdjacent</A
+> :: (Ord a, Enum a) =&gt; a -&gt; a -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+><SPAN CLASS="keyword"
+>data</SPAN
+> <A HREF="#t%3ABoundary"
+>Boundary</A
+> a</TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+>= <A HREF="#v%3ABoundaryAbove"
+>BoundaryAbove</A
+> a</TD
+></TR
+><TR
+><TD CLASS="decl"
+>| <A HREF="#v%3ABoundaryBelow"
+>BoundaryBelow</A
+> a</TD
+></TR
+><TR
+><TD CLASS="decl"
+>| <A HREF="#v%3ABoundaryAboveAll"
+>BoundaryAboveAll</A
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+>| <A HREF="#v%3ABoundaryBelowAll"
+>BoundaryBelowAll</A
+></TD
+></TR
+></TABLE
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3Aabove"
+>above</A
+> :: Ord v =&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> v -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3A%2F%3E%2F"
+>(/&gt;/)</A
+> :: Ord v =&gt; v -&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> v -&gt; Bool</TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section1"
+>Documentation</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><SPAN CLASS="keyword"
+>class</SPAN
+> Ord a =&gt; <A NAME="t%3ADiscreteOrdered"
+></A
+><B
+>DiscreteOrdered</B
+> a  <SPAN CLASS="keyword"
+>where</SPAN
+></TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="ndoc"
+><P
+>Distinguish between dense and sparse ordered types.  A dense type is 
+one in which any two values <TT
+>v1 &lt; v2</TT
+> have a third value <TT
+>v3</TT
+> such that 
+<TT
+>v1 &lt; v3 &lt; v2</TT
+>.
+</P
+><P
+>In theory the floating types are dense, although in practice they can only have
+finitely many values.  This class treats them as dense.
+</P
+><P
+>Tuples up to 4 members are declared as instances.  Larger tuples may be added
+if necessary.
+</P
+><P
+>This approach was suggested by Ben Rudiak-Gould on comp.lang.functional.
+</P
+></TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="section4"
+>Methods</TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+><A NAME="v%3Aadjacent"
+></A
+><B
+>adjacent</B
+> :: a -&gt; a -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Two values <TT
+>x</TT
+> and <TT
+>y</TT
+> are adjacent if <TT
+>x &lt; y</TT
+> and there does not 
+ exist a third value between them.  Always <TT
+>False</TT
+> for dense types.
+</TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="section4"
+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:DiscreteOrdered')" ALT="show/hide"
+> Instances</TD
+></TR
+><TR
+><TD CLASS="body"
+><DIV ID="i:DiscreteOrdered" STYLE="display:block;"
+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> Bool</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> Char</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> Double</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> Float</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> Int</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> Integer</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> Ordering</TD
+></TR
+><TR
+><TD CLASS="decl"
+>(Ord a, <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> b) =&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> (a, b)</TD
+></TR
+><TR
+><TD CLASS="decl"
+>(Ord a, Ord b, <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> c) =&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> (a, b, c)</TD
+></TR
+><TR
+><TD CLASS="decl"
+>(Ord a, Ord b, Ord c, <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> d) =&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> (a, b, c, d)</TD
+></TR
+><TR
+><TD CLASS="decl"
+>Integral a =&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> (Ratio a)</TD
+></TR
+><TR
+><TD CLASS="decl"
+>Ord a =&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> [a]</TD
+></TR
+></TABLE
+></DIV
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3Aadjacent"
+></A
+><B
+>adjacent</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; a -&gt; a -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Two values <TT
+>x</TT
+> and <TT
+>y</TT
+> are adjacent if <TT
+>x &lt; y</TT
+> and there does not 
+ exist a third value between them.  Always <TT
+>False</TT
+> for dense types.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3AenumAdjacent"
+></A
+><B
+>enumAdjacent</B
+> :: (Ord a, Enum a) =&gt; a -&gt; a -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Check adjacency for sparse enumerated types (i.e. where there
+ is no value between <TT
+>x</TT
+> and <TT
+>succ x</TT
+>).  Use as the definition of
+ <A HREF="adjacent.html"
+>adjacent</A
+> for most enumerated types.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3AboundedAdjacent"
+></A
+><B
+>boundedAdjacent</B
+> :: (Ord a, Enum a) =&gt; a -&gt; a -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Check adjacency, allowing for case where x = maxBound.  Use as the
+ definition of <A HREF="adjacent.html"
+>adjacent</A
+> for bounded enumerated types such as Int and Char.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><SPAN CLASS="keyword"
+>data</SPAN
+> <A NAME="t%3ABoundary"
+></A
+><B
+>Boundary</B
+> a</TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="ndoc"
+><P
+>A Boundary is a division of an ordered type into values above 
+and below the boundary.  No value can sit on a boundary.
+</P
+><P
+>Known bug: for Bounded types 
+</P
+><UL
+><LI
+><PRE
+>BoundaryAbove maxBound &lt; BoundaryAboveAll</PRE
+></LI
+><LI
+><PRE
+>BoundaryBelow minBound &gt; BoundaryBelowAll</PRE
+></LI
+></UL
+><P
+>This is incorrect because there are no possible values in 
+between the left and right sides of these inequalities. 
+</P
+></TD
+></TR
+><TR
+><TD CLASS="section4"
+>Constructors</TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"
+><TR
+><TD CLASS="arg"
+><A NAME="v%3ABoundaryAbove"
+></A
+><B
+>BoundaryAbove</B
+> a</TD
+><TD CLASS="rdoc"
+>The argument is the highest value below the boundary.
+</TD
+></TR
+><TR
+><TD CLASS="arg"
+><A NAME="v%3ABoundaryBelow"
+></A
+><B
+>BoundaryBelow</B
+> a</TD
+><TD CLASS="rdoc"
+>The argument is the lowest value above the boundary.
+</TD
+></TR
+><TR
+><TD CLASS="arg"
+><A NAME="v%3ABoundaryAboveAll"
+></A
+><B
+>BoundaryAboveAll</B
+></TD
+><TD CLASS="rdoc"
+>The boundary above all values.
+</TD
+></TR
+><TR
+><TD CLASS="arg"
+><A NAME="v%3ABoundaryBelowAll"
+></A
+><B
+>BoundaryBelowAll</B
+></TD
+><TD CLASS="rdoc"
+>The boundary below all values.
+</TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="section4"
+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:Boundary')" ALT="show/hide"
+> Instances</TD
+></TR
+><TR
+><TD CLASS="body"
+><DIV ID="i:Boundary" STYLE="display:block;"
+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+>Arbitrary a =&gt; Arbitrary (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a)</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; Eq (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a)</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; Ord (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a)</TD
+></TR
+><TR
+><TD CLASS="decl"
+>Show a =&gt; Show (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a)</TD
+></TR
+></TABLE
+></DIV
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3Aabove"
+></A
+><B
+>above</B
+> :: Ord v =&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> v -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>True if the value is above the boundary, false otherwise.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3A%2F%3E%2F"
+></A
+><B
+>(/&gt;/)</B
+> :: Ord v =&gt; v -&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Same as <TT
+><A HREF="Data-Ranged-Boundaries.html#v%3Aabove"
+>above</A
+></TT
+>, but with the arguments reversed for more intuitive infix
+ usage.   
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="botbar"
+>Produced by <A HREF="http://www.haskell.org/haddock/"
+>Haddock</A
+> version 0.8</TD
+></TR
+></TABLE
+></BODY
+></HTML
+>
diff --git a/Doc/Data-Ranged-RangedSet.html b/Doc/Data-Ranged-RangedSet.html
new file mode 100644
--- /dev/null
+++ b/Doc/Data-Ranged-RangedSet.html
@@ -0,0 +1,1456 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--Rendered using the Haskell Html Library v0.2-->
+<HTML
+><HEAD
+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"
+><TITLE
+>Data.Ranged.RangedSet</TITLE
+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"
+><SCRIPT SRC="haddock.js" TYPE="text/javascript"
+></SCRIPT
+></HEAD
+><BODY
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="topbar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "
+></TD
+><TD CLASS="title"
+></TD
+><TD CLASS="topbut"
+><A HREF="index.html"
+>Contents</A
+></TD
+><TD CLASS="topbut"
+><A HREF="doc-index.html"
+>Index</A
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="modulebar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><FONT SIZE="6"
+>Data.Ranged.RangedSet</FONT
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="section4"
+><B
+>Contents</B
+></TD
+></TR
+><TR
+><TD
+><DL
+><DT
+><A HREF="#1"
+>Ranged Set Type
+</A
+></DT
+><DT
+><A HREF="#2"
+>Ranged Set construction functions and their Preconditions
+</A
+></DT
+><DT
+><A HREF="#3"
+>Predicates
+</A
+></DT
+><DT
+><A HREF="#4"
+>Set Operations
+</A
+></DT
+><DT
+><A HREF="#5"
+>Useful Sets
+</A
+></DT
+><DT
+><A HREF="#6"
+>QuickCheck Properties
+</A
+></DT
+><DD
+><DL
+><DT
+><A HREF="#7"
+>Construction
+</A
+></DT
+><DT
+><A HREF="#8"
+>Basic Operations
+</A
+></DT
+><DT
+><A HREF="#9"
+>Some Identities and Inequalities
+</A
+></DT
+></DL
+></DD
+></DL
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section1"
+>Synopsis</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+><SPAN CLASS="keyword"
+>data</SPAN
+> <A HREF="#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetRanges"
+>rSetRanges</A
+> :: <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v]</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3AmakeRangedSet"
+>makeRangedSet</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3AunsafeRangedSet"
+>unsafeRangedSet</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3AvalidRangeList"
+>validRangeList</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3AnormaliseRangeList"
+>normaliseRangeList</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v]</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSingleton"
+>rSingleton</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetIsEmpty"
+>rSetIsEmpty</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3A-%3F-"
+>(-?-)</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetHas"
+>rSetHas</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3A-%3C%3D-"
+>(-&lt;=-)</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetIsSubset"
+>rSetIsSubset</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3A-%3C-"
+>(-&lt;-)</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetIsSubsetStrict"
+>rSetIsSubsetStrict</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3A-%5C%2F-"
+>(-\/-)</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetUnion"
+>rSetUnion</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3A-%2F%5C-"
+>(-/\-)</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetIntersection"
+>rSetIntersection</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3A-%21-"
+>(-!-)</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetDifference"
+>rSetDifference</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetNegation"
+>rSetNegation</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetEmpty"
+>rSetEmpty</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetFull"
+>rSetFull</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArSetUnfold"
+>rSetUnfold</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a -&gt; (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a -&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a) -&gt; (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a -&gt; Maybe (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a)) -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a</TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="1"
+>Ranged Set Type
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><SPAN CLASS="keyword"
+>data</SPAN
+> <A NAME="t%3ARSet"
+></A
+><B
+>RSet</B
+> v</TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="ndoc"
+>An RSet (for Ranged Set) is a list of ranges.  The ranges must be sorted
+ and not overlap.
+</TD
+></TR
+><TR
+><TD CLASS="section4"
+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:RSet')" ALT="show/hide"
+> Instances</TD
+></TR
+><TR
+><TD CLASS="body"
+><DIV ID="i:RSet" STYLE="display:block;"
+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+>(Arbitrary v, <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v, Show v) =&gt; Arbitrary (<A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v)</TD
+></TR
+><TR
+><TD CLASS="decl"
+>(<A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v, ??? v) =&gt; Eq (<A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v)</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; Monoid (<A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a)</TD
+></TR
+><TR
+><TD CLASS="decl"
+>(<A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v, ??? v) =&gt; Show (<A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v)</TD
+></TR
+></TABLE
+></DIV
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetRanges"
+></A
+><B
+>rSetRanges</B
+> :: <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v]</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="2"
+>Ranged Set construction functions and their Preconditions
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3AmakeRangedSet"
+></A
+><B
+>makeRangedSet</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Create a new Ranged Set from a list of ranges.  The list may contain
+ ranges that overlap or are not in ascending order.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3AunsafeRangedSet"
+></A
+><B
+>unsafeRangedSet</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Create a new Ranged Set from a list of ranges. <TT
+>validRangeList ranges</TT
+> 
+ must return <TT
+>True</TT
+>.  This precondition is not checked.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3AvalidRangeList"
+></A
+><B
+>validRangeList</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Determine if the ranges in the list are both in order and non-overlapping.
+ If so then they are suitable input for the unsafeRangedSet function.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3AnormaliseRangeList"
+></A
+><B
+>normaliseRangeList</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v]</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Rearrange and merge the ranges in the list so that they are in order and
+ non-overlapping.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSingleton"
+></A
+><B
+>rSingleton</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Create a Ranged Set from a single element.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="3"
+>Predicates
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetIsEmpty"
+></A
+><B
+>rSetIsEmpty</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>True if the set has no members.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3A-%3F-"
+></A
+><B
+>(-?-)</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetHas"
+></A
+><B
+>rSetHas</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>True if the value is within the ranged set.  Infix precedence is left 5.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3A-%3C%3D-"
+></A
+><B
+>(-&lt;=-)</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetIsSubset"
+></A
+><B
+>rSetIsSubset</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+><P
+>True if the first argument is a subset of the second argument, or is 
+ equal. 
+</P
+><P
+>Infix precedence is left 5.
+</P
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3A-%3C-"
+></A
+><B
+>(-&lt;-)</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetIsSubsetStrict"
+></A
+><B
+>rSetIsSubsetStrict</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+><P
+>True if the first argument is a strict subset of the second argument.
+</P
+><P
+>Infix precedence is left 5.
+</P
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="4"
+>Set Operations
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3A-%5C%2F-"
+></A
+><B
+>(-\/-)</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetUnion"
+></A
+><B
+>rSetUnion</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Set union for ranged sets.  Infix precedence is left 6.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3A-%2F%5C-"
+></A
+><B
+>(-/\-)</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetIntersection"
+></A
+><B
+>rSetIntersection</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Set intersection for ranged sets.  Infix precedence is left 7.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3A-%21-"
+></A
+><B
+>(-!-)</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetDifference"
+></A
+><B
+>rSetDifference</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Set difference.  Infix precedence is left 6.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetNegation"
+></A
+><B
+>rSetNegation</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a -&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Set negation.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="5"
+>Useful Sets
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetEmpty"
+></A
+><B
+>rSetEmpty</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a</TD
+></TR
+><TR
+><TD CLASS="doc"
+>The empty set.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetFull"
+></A
+><B
+>rSetFull</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a</TD
+></TR
+><TR
+><TD CLASS="doc"
+>The set that contains everything.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArSetUnfold"
+></A
+><B
+>rSetUnfold</B
+></TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="arg"
+>:: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a</TD
+><TD CLASS="rdoc"
+></TD
+></TR
+><TR
+><TD CLASS="arg"
+>=&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a</TD
+><TD CLASS="rdoc"
+>A first lower boundary.
+</TD
+></TR
+><TR
+><TD CLASS="arg"
+>-&gt; (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a -&gt; <A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a)</TD
+><TD CLASS="rdoc"
+>A function from a lower boundary to an upper boundary, which must
+ return a result greater than the argument (not checked).
+</TD
+></TR
+><TR
+><TD CLASS="arg"
+>-&gt; (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a -&gt; Maybe (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> a))</TD
+><TD CLASS="rdoc"
+>A function from a lower boundary to <TT
+>Maybe</TT
+> the successor lower 
+ boundary, which must return a result greater than the argument 
+ (not checked).
+</TD
+></TR
+><TR
+><TD CLASS="arg"
+>-&gt; <A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>RSet</A
+> a</TD
+><TD CLASS="rdoc"
+></TD
+></TR
+><TR
+><TD CLASS="ndoc" COLSPAN="2"
+>Construct a range set.
+</TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="6"
+>QuickCheck Properties
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section3"
+><A NAME="7"
+>Construction
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="doc"
+><P
+>A normalised range list is valid for unsafeRangedSet
+</P
+><PRE
+> prop_validNormalised ls = validRangeList $ normaliseRangeList ls
+    where types = ls :: [Range Double]
+</PRE
+><P
+>Iff a value is in a range list then it is in a ranged set
+constructed from that list.
+</P
+><PRE
+> prop_has ls v = (ls `rangeListHas` v) == rangedSet ls -?- v
+</PRE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section3"
+><A NAME="8"
+>Basic Operations
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="doc"
+><P
+>Iff a value is in either of two ranged sets then it is in the union of
+those two sets.
+</P
+><PRE
+> prop_union rs1 rs2 v =
+    (rs1 -?- v || rs2 -?- v) == ((rs1 -\/- rs2) -?- v)
+</PRE
+><P
+>Iff a value is in both of two ranged sets then it is in the intersection
+of those two sets.
+</P
+><PRE
+> prop_intersection rs1 rs2 v =
+    (rs1 -?- v &amp;&amp; rs2 -?- v) == ((rs1 -/\- rs2) -?- v)
+</PRE
+><P
+>Iff a value is in ranged set 1 and not in ranged set 2 then it is in the
+difference of the two.
+</P
+><PRE
+> prop_difference rs1 rs2 v = 
+    (rs1 -?- v &amp;&amp; not (rs2 -?- v)) == ((rs1 -!- rs2) -?- v)
+</PRE
+><P
+>Iff a value is not in a ranged set then it is in its negation.      
+</P
+><PRE
+> prop_negation rs v = rs -?- v == not (rSetNegation rs -?- v)
+</PRE
+><P
+>A set that contains a value is not empty
+</P
+><PRE
+> prop_not_empty rs v = (rs -?- v) ==&gt; not (rSetIsEmpty rs)
+</PRE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section3"
+><A NAME="9"
+>Some Identities and Inequalities
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="doc"
+><P
+>The empty set has no members.
+</P
+><PRE
+> prop_empty v = not (rSetEmpty -?- v)
+</PRE
+><P
+>The full set has every member.
+</P
+><PRE
+> prop_full v = rSetFull -?- v
+</PRE
+><P
+>The intersection of a set with its negation is empty.
+</P
+><PRE
+> prop_empty_intersection rs =
+    rSetIsEmpty (rs -/\- rSetNegation rs) 
+</PRE
+><P
+>The union of a set with its negation is full.
+</P
+><PRE
+> prop_full_union rs v =
+    rSetIsFull (rs -\/- rSetNegation rs)
+</PRE
+><P
+>The union of two sets is the non-strict superset of both.
+</P
+><PRE
+> prop_union_superset rs1 rs2 =
+    rs1 -&lt;=- u &amp;&amp; rs2 -&lt;=- u 
+    where
+       u = rs1 -\/- rs2
+</PRE
+><P
+>The intersection of two sets is the non-strict subset of both.
+</P
+><PRE
+> prop_intersection_subset rs1 rs2 =
+    i -&lt;=- rs1 &amp;&amp; i -&lt;=- rs2
+    where
+       i = rs1 -/\- rs2
+</PRE
+><P
+>The difference of two sets intersected with the subtractand is empty.
+</P
+><PRE
+> prop_diff_intersect rs1 rs2 =
+    rSetIsEmpty ((rs1 -!- rs2) -/\- rs2)
+</PRE
+><P
+>A set is the non-strict subset of itself.
+</P
+><PRE
+> prop_subset rs = rs -&lt;=- rs
+</PRE
+><P
+>A set is not the strict subset of itself.
+</P
+><PRE
+> prop_strict_subset rs = not (rs -&lt;- rs)
+</PRE
+><P
+>If rs1 - rs2 is not empty then the union of rs1 and rs2 will be a strict 
+superset of rs2.
+</P
+><PRE
+> prop_union_strict_superset rs1 rs2 =
+    (not $ rSetIsEmpty (rs1 -!- rs2))
+    ==&gt; (rs2 -&lt;- (rs1 -\/- rs2))
+</PRE
+><P
+>Intersection commutes
+</P
+><PRE
+> prop_intersection_commutes rs1 rs2 =
+    (rs1 -/\- rs2) == (rs2 -/\- rs1)
+</PRE
+><P
+>Union commutes
+</P
+><PRE
+> prop_union_commutes rs1 rs2 =
+    (rs1 -\/- rs2) == (rs2 -\/- rs1)
+</PRE
+><P
+>Intersection associates
+</P
+><PRE
+> prop_intersection_associates rs1 rs2 rs3 =
+    ((rs1 -/\- rs2) -/\- rs3) == (rs1 -/\- (rs2 -/\- rs3))
+</PRE
+><P
+>Union associates
+</P
+><PRE
+> prop_union_associates rs1 rs2 rs3 =
+    ((rs1 -\/- rs2) -\/- rs3) == (rs1 -\/- (rs2 -\/- rs3))
+</PRE
+><P
+>De Morgan's Law for Intersection
+</P
+><PRE
+> prop_de_morgan_intersection rs1 rs2 =
+    rSetNegation (rs1 -/\- rs2) == (rSetNegation rs1 -\/- rSetNegation rs2)
+</PRE
+><P
+>De Morgan's Law for Union
+</P
+><PRE
+> prop_de_morgan_union rs1 rs2 =
+    rSetNegation (rs1 -\/- rs2) == (rSetNegation rs1 -/\- rSetNegation rs2)
+</PRE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="botbar"
+>Produced by <A HREF="http://www.haskell.org/haddock/"
+>Haddock</A
+> version 0.8</TD
+></TR
+></TABLE
+></BODY
+></HTML
+>
diff --git a/Doc/Data-Ranged-Ranges.html b/Doc/Data-Ranged-Ranges.html
new file mode 100644
--- /dev/null
+++ b/Doc/Data-Ranged-Ranges.html
@@ -0,0 +1,838 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--Rendered using the Haskell Html Library v0.2-->
+<HTML
+><HEAD
+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"
+><TITLE
+>Data.Ranged.Ranges</TITLE
+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"
+><SCRIPT SRC="haddock.js" TYPE="text/javascript"
+></SCRIPT
+></HEAD
+><BODY
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="topbar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "
+></TD
+><TD CLASS="title"
+></TD
+><TD CLASS="topbut"
+><A HREF="index.html"
+>Contents</A
+></TD
+><TD CLASS="topbut"
+><A HREF="doc-index.html"
+>Index</A
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="modulebar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><FONT SIZE="6"
+>Data.Ranged.Ranges</FONT
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="section4"
+><B
+>Contents</B
+></TD
+></TR
+><TR
+><TD
+><DL
+><DT
+><A HREF="#1"
+>Construction
+</A
+></DT
+><DT
+><A HREF="#2"
+>Predicates
+</A
+></DT
+><DT
+><A HREF="#3"
+>Membership
+</A
+></DT
+><DT
+><A HREF="#4"
+>Set Operations
+</A
+></DT
+><DT
+><A HREF="#5"
+>QuickCheck properties
+</A
+></DT
+></DL
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section1"
+>Description</TD
+></TR
+><TR
+><TD CLASS="doc"
+>A range has an upper and lower boundary.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section1"
+>Synopsis</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+><SPAN CLASS="keyword"
+>data</SPAN
+> <A HREF="#t%3ARange"
+>Range</A
+> v = <A HREF="#v%3ARange"
+>Range</A
+> {<TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="recfield"
+><A HREF="#v%3ArangeLower"
+>rangeLower</A
+>, <A HREF="#v%3ArangeUpper"
+>rangeUpper</A
+> :: (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> v)</TD
+></TR
+></TABLE
+>}</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3AemptyRange"
+>emptyRange</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3AfullRange"
+>fullRange</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArangeIsEmpty"
+>rangeIsEmpty</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArangeOverlap"
+>rangeOverlap</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArangeEncloses"
+>rangeEncloses</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArangeSingletonValue"
+>rangeSingletonValue</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; Maybe v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArangeHas"
+>rangeHas</A
+> :: Ord v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArangeListHas"
+>rangeListHas</A
+> :: Ord v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3AsingletonRange"
+>singletonRange</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArangeIntersection"
+>rangeIntersection</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArangeUnion"
+>rangeUnion</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v]</TD
+></TR
+><TR
+><TD CLASS="s8"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="#v%3ArangeDifference"
+>rangeDifference</A
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v]</TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="1"
+>Construction
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><SPAN CLASS="keyword"
+>data</SPAN
+> <A NAME="t%3ARange"
+></A
+><B
+>Range</B
+> v</TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="ndoc"
+>A Range has upper and lower boundaries.
+</TD
+></TR
+><TR
+><TD CLASS="section4"
+>Constructors</TD
+></TR
+><TR
+><TD CLASS="body"
+><TABLE CLASS="vanilla" CELLSPACING="5" CELLPADDING="0"
+><TR
+><TD CLASS="arg"
+><A NAME="v%3ARange"
+></A
+><B
+>Range</B
+></TD
+><TD CLASS="rdoc"
+></TD
+></TR
+><TR
+><TD CLASS="body" COLSPAN="2"
+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"
+><TR
+><TD CLASS="arg"
+><A NAME="v%3ArangeLower"
+></A
+><B
+>rangeLower</B
+>, <A NAME="v%3ArangeUpper"
+></A
+><B
+>rangeUpper</B
+> :: (<A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Boundary</A
+> v)</TD
+><TD CLASS="rdoc"
+></TD
+></TR
+></TABLE
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="section4"
+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:Range')" ALT="show/hide"
+> Instances</TD
+></TR
+><TR
+><TD CLASS="body"
+><DIV ID="i:Range" STYLE="display:block;"
+><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0"
+><TR
+><TD CLASS="decl"
+>(Arbitrary v, <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v, Show v) =&gt; Arbitrary (<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v)</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; Eq (<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> a)</TD
+></TR
+><TR
+><TD CLASS="decl"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a =&gt; Ord (<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> a)</TD
+></TR
+><TR
+><TD CLASS="decl"
+>(Show a, <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> a) =&gt; Show (<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> a)</TD
+></TR
+></TABLE
+></DIV
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3AemptyRange"
+></A
+><B
+>emptyRange</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>The empty range
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3AfullRange"
+></A
+><B
+>fullRange</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>The full range.  All values are within it.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="2"
+>Predicates
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArangeIsEmpty"
+></A
+><B
+>rangeIsEmpty</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>A range is empty unless its upper boundary is greater than its lower
+ boundary.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArangeOverlap"
+></A
+><B
+>rangeOverlap</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Two ranges overlap if their intersection is non-empty.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArangeEncloses"
+></A
+><B
+>rangeEncloses</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>The first range encloses the second if every value in the second range is 
+ also within the first range.  If the second range is empty then this is
+ always true.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArangeSingletonValue"
+></A
+><B
+>rangeSingletonValue</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; Maybe v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>If the range is a singleton, returns <TT
+>Just</TT
+> the value.  Otherwise returns
+ <TT
+>Nothing</TT
+>.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="3"
+>Membership
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArangeHas"
+></A
+><B
+>rangeHas</B
+> :: Ord v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>True if the value is within the range.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArangeListHas"
+></A
+><B
+>rangeListHas</B
+> :: Ord v =&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v] -&gt; v -&gt; Bool</TD
+></TR
+><TR
+><TD CLASS="doc"
+>True if the value is within one of the ranges.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="4"
+>Set Operations
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3AsingletonRange"
+></A
+><B
+>singletonRange</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>A range containing a single value
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArangeIntersection"
+></A
+><B
+>rangeIntersection</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v</TD
+></TR
+><TR
+><TD CLASS="doc"
+>Intersection of two ranges, if any.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArangeUnion"
+></A
+><B
+>rangeUnion</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v]</TD
+></TR
+><TR
+><TD CLASS="doc"
+><P
+>Union of two ranges.  Returns one or two results.
+</P
+><P
+>If there are two results then they are guaranteed to have a non-empty
+ gap in between, but may not be in ascending order.
+</P
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+><A NAME="v%3ArangeDifference"
+></A
+><B
+>rangeDifference</B
+> :: <A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>DiscreteOrdered</A
+> v =&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; <A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v -&gt; [<A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Range</A
+> v]</TD
+></TR
+><TR
+><TD CLASS="doc"
+><TT
+>range1</TT
+> minus <TT
+>range2</TT
+>.  Returns zero, one or two results.  Multiple 
+ results are guaranteed to have non-empty gaps in between, but may not be in 
+ ascending order.
+</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section2"
+><A NAME="5"
+>QuickCheck properties
+</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="doc"
+><P
+>Range union
+</P
+><PRE
+> prop_union r1 r2 n =
+    (r1 `rangeHas` n || r2 `rangeHas` n) 
+    == (r1 `rangeUnion` r2) `rangeListHas` n
+</PRE
+><P
+>Range intersection
+</P
+><PRE
+> prop_intersection r1 r2 n =
+    (r1 `rangeHas` n &amp;&amp; r2 `rangeHas` n)
+    == (r1 `rangeIntersection` r2) `rangeHas` n
+</PRE
+><P
+>Range difference
+</P
+><PRE
+> prop_difference r1 r2 n =
+    (r1 `rangeHas` n &amp;&amp; not (r2 `rangeHas` n))
+    == (r1 `rangeDifference` r2) `rangeListHas` n
+</PRE
+><P
+>Singleton range
+</P
+><PRE
+> prop_singletonHas v =
+    singletonRange v `rangeHas` v
+</PRE
+><PRE
+> prop_singletonConverse v =
+    rangeSingletonValue (singletonRange v) == Just v
+</PRE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="botbar"
+>Produced by <A HREF="http://www.haskell.org/haddock/"
+>Haddock</A
+> version 0.8</TD
+></TR
+></TABLE
+></BODY
+></HTML
+>
diff --git a/Doc/Data-Ranged.html b/Doc/Data-Ranged.html
new file mode 100644
--- /dev/null
+++ b/Doc/Data-Ranged.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--Rendered using the Haskell Html Library v0.2-->
+<HTML
+><HEAD
+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"
+><TITLE
+>Data.Ranged</TITLE
+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"
+><SCRIPT SRC="haddock.js" TYPE="text/javascript"
+></SCRIPT
+></HEAD
+><BODY
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="topbar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "
+></TD
+><TD CLASS="title"
+></TD
+><TD CLASS="topbut"
+><A HREF="index.html"
+>Contents</A
+></TD
+><TD CLASS="topbut"
+><A HREF="doc-index.html"
+>Index</A
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="modulebar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><FONT SIZE="6"
+>Data.Ranged</FONT
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="section1"
+>Documentation</TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+>module <A HREF="Data-Ranged-Boundaries.html"
+>Data.Ranged.Boundaries</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+>module <A HREF="Data-Ranged-Ranges.html"
+>Data.Ranged.Ranges</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="decl"
+>module <A HREF="Data-Ranged-RangedSet.html"
+>Data.Ranged.RangedSet</A
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="botbar"
+>Produced by <A HREF="http://www.haskell.org/haddock/"
+>Haddock</A
+> version 0.8</TD
+></TR
+></TABLE
+></BODY
+></HTML
+>
diff --git a/Doc/doc-index.html b/Doc/doc-index.html
new file mode 100644
--- /dev/null
+++ b/Doc/doc-index.html
@@ -0,0 +1,454 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--Rendered using the Haskell Html Library v0.2-->
+<HTML
+><HEAD
+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"
+><TITLE
+> (Index)</TITLE
+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"
+></HEAD
+><BODY
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="topbar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "
+></TD
+><TD CLASS="title"
+></TD
+><TD CLASS="topbut"
+><A HREF="index.html"
+>Contents</A
+></TD
+><TD CLASS="topbut"
+><A HREF="doc-index.html"
+>Index</A
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD
+><TABLE CELLPADDING="0" CELLSPACING="5"
+><TR
+><TD CLASS="indexentry"
+>-!-</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3A-%21-"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>-/\-</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3A-%2F%5C-"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>-&lt;-</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3A-%3C-"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>-&lt;=-</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3A-%3C%3D-"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>-?-</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3A-%3F-"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>-\/-</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3A-%5C%2F-"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>/&gt;/</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#v%3A%2F%3E%2F"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>Boundary</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#t%3ABoundary"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>BoundaryAbove</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#v%3ABoundaryAbove"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>BoundaryAboveAll</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#v%3ABoundaryAboveAll"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>BoundaryBelow</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#v%3ABoundaryBelow"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>BoundaryBelowAll</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#v%3ABoundaryBelowAll"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>DiscreteOrdered</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#t%3ADiscreteOrdered"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>RSet</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#t%3ARSet"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry" COLSPAN="2"
+>Range</TD
+></TR
+><TR
+><TD CLASS="indexannot"
+>1 (Type/Class)</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#t%3ARange"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexannot"
+>2 (Data Constructor)</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ARange"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>above</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#v%3Aabove"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>adjacent</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#v%3Aadjacent"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>boundedAdjacent</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#v%3AboundedAdjacent"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>emptyRange</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3AemptyRange"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>enumAdjacent</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Boundaries.html#v%3AenumAdjacent"
+>Data.Ranged.Boundaries</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>fullRange</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3AfullRange"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>makeRangedSet</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3AmakeRangedSet"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>normaliseRangeList</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3AnormaliseRangeList"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetDifference</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetDifference"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetEmpty</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetEmpty"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetFull</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetFull"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetHas</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetHas"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetIntersection</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetIntersection"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetIsEmpty</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetIsEmpty"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetIsSubset</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetIsSubset"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetIsSubsetStrict</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetIsSubsetStrict"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetNegation</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetNegation"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetRanges</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetRanges"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetUnfold</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetUnfold"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSetUnion</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSetUnion"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rSingleton</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3ArSingleton"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeDifference</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeDifference"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeEncloses</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeEncloses"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeHas</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeHas"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeIntersection</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeIntersection"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeIsEmpty</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeIsEmpty"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeListHas</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeListHas"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeLower</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeLower"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeOverlap</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeOverlap"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeSingletonValue</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeSingletonValue"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeUnion</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeUnion"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>rangeUpper</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3ArangeUpper"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>singletonRange</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-Ranges.html#v%3AsingletonRange"
+>Data.Ranged.Ranges</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>unsafeRangedSet</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3AunsafeRangedSet"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+><TR
+><TD CLASS="indexentry"
+>validRangeList</TD
+><TD CLASS="indexlinks"
+><A HREF="Data-Ranged-RangedSet.html#v%3AvalidRangeList"
+>Data.Ranged.RangedSet</A
+>, Data.Ranged</TD
+></TR
+></TABLE
+></TD
+></TR
+></TABLE
+></BODY
+></HTML
+>
diff --git a/Doc/index.html b/Doc/index.html
new file mode 100644
--- /dev/null
+++ b/Doc/index.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--Rendered using the Haskell Html Library v0.2-->
+<HTML
+><HEAD
+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"
+><TITLE
+></TITLE
+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"
+><SCRIPT SRC="haddock.js" TYPE="text/javascript"
+></SCRIPT
+></HEAD
+><BODY
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD CLASS="topbar"
+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD
+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "
+></TD
+><TD CLASS="title"
+></TD
+><TD CLASS="topbut"
+><A HREF="index.html"
+>Contents</A
+></TD
+><TD CLASS="topbut"
+><A HREF="doc-index.html"
+>Index</A
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="section1"
+>Modules</TD
+></TR
+><TR
+><TD
+><TABLE CLASS="vanilla2" CELLSPACING="0" CELLPADDING="0"
+><TR
+><TD STYLE="width: 50em"
+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'n:0')" ALT="show/hide"
+>Data</TD
+><TD
+></TD
+><TD
+></TD
+></TR
+><TR
+><TD STYLE="padding: 0; padding-left: 2em" COLSPAN="3"
+><TABLE CLASS="vanilla2" CELLSPACING="0" CELLPADDING="0" ID="n:0" STYLE="display:block;"
+><TR
+><TD STYLE="width: 48em"
+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'n:1')" ALT="show/hide"
+><A HREF="Data-Ranged.html"
+>Data.Ranged</A
+></TD
+><TD
+></TD
+><TD
+></TD
+></TR
+><TR
+><TD STYLE="padding: 0; padding-left: 2em" COLSPAN="3"
+><TABLE CLASS="vanilla2" CELLSPACING="0" CELLPADDING="0" ID="n:1" STYLE="display:block;"
+><TR
+><TD STYLE="padding-left: 1.25em;width: 46em"
+><A HREF="Data-Ranged-Boundaries.html"
+>Data.Ranged.Boundaries</A
+></TD
+><TD
+></TD
+><TD
+></TD
+></TR
+><TR
+><TD STYLE="padding-left: 1.25em;width: 46em"
+><A HREF="Data-Ranged-RangedSet.html"
+>Data.Ranged.RangedSet</A
+></TD
+><TD
+></TD
+><TD
+></TD
+></TR
+><TR
+><TD STYLE="padding-left: 1.25em;width: 46em"
+><A HREF="Data-Ranged-Ranges.html"
+>Data.Ranged.Ranges</A
+></TD
+><TD
+></TD
+><TD
+></TD
+></TR
+></TABLE
+></TD
+></TR
+></TABLE
+></TD
+></TR
+></TABLE
+></TD
+></TR
+><TR
+><TD CLASS="s15"
+></TD
+></TR
+><TR
+><TD CLASS="botbar"
+>Produced by <A HREF="http://www.haskell.org/haddock/"
+>Haddock</A
+> version 0.8</TD
+></TR
+></TABLE
+></BODY
+></HTML
+>
diff --git a/INSTALL.txt b/INSTALL.txt
new file mode 100644
--- /dev/null
+++ b/INSTALL.txt
@@ -0,0 +1,14 @@
+As user, from within the project directory:
+
+   runghc Setup.hs configure
+   runghc Setup.hs build
+
+As root or administrator:
+
+   runghc Setup.hs install
+   
+If you have Haddock then generate the documentation with:
+
+   runghc Setup.hs haddock
+   
+If you use Hugs then type "runhugs" instead of "runghc".
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,30 @@
+Copyright (c) 2005, Paul Johnson
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions 
+are met:
+
+    * Redistributions of source code must retain the above copyright 
+      notice, this list of conditions and the following disclaimer.
+      
+    * Redistributions in binary form must reproduce the above copyright 
+      notice, this list of conditions and the following disclaimer in 
+      the documentation and/or other materials provided with the 
+      distribution.
+      
+    * Neither the name of the Ranged Sets project nor the names of its 
+      contributors may be used to endorse or promote products derived 
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.txt b/README.txt
new file mode 100644
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,119 @@
+Ranged Sets for Haskell
+=======================
+
+Ranged sets allow programming with sets of values that are described
+by a list of ranges.  A value is a member of the set if it lies within
+one of the ranges.  The ranges in a set are ordered and
+non-overlapping, so the standard set operations can be implemented by
+merge algorithms in O(n) time.
+
+License
+-------
+
+Currently the Ranged Set library is under the BSD 3 license.  This is
+a very permissive license.  I am hoping that Ranged Sets will
+eventually become part of the Base library, and at that point the
+implementation will have to be issued under the same license as the
+rest of the library (which in practice probably means different
+licenses for different compiler versions).  As I understand it the BSD
+3 license will allow this without me having to get either assignment
+of copyright or explicit permission from everyone who submits
+contributions.
+
+
+Boundaries
+----------
+
+Module Data.Ranged.Boundaries defines the Boundary type.  A boundary
+divides an ordered type into values above and below the boundary.  No
+value can ever sit on a boundary.
+
+Two boundaries are equal if they divide the values at the same point.
+This definition of equality causes an implementation problem because
+some types are "discrete".  For instance there is no value between the
+characters 'a' and 'b', or between the integers 3 and 4.  However
+there are values between 3.0 and 4.0.  Similarly for strings, there
+are values between "a" and "b" such as "aa", "ab", and so on.  This is
+important because "BoundaryAbove 3" is equal to "BoundaryBelow 4".  3
+is below both boundaries, and 4 is above both.  Hence they divide the
+integers at the same place.  But on the other hand "BoundaryAbove 3.0"
+and "BoundaryBelow 4.0" are not equal because 3.5 is above the first
+and below the second.
+
+To solve this the DiscreteOrdered class is defined, which provides a
+function "adjacent".  Two values x1 and x3 are adjacent if x1 < x3 and
+there does not exist an x2 such that x1 < x2 < x3.  This provides the
+distinction necessary for boundary equality to be defined for all
+ordered types.  The ordered types from the prelude are instances of
+DiscreteOrdered, and others can be added by defining "adjacent".  The
+functions "enumAdjacent" and "boundedAdjacent" are provided for
+instances of Enum and Bounded.  Lists and tuples of DiscreteOrdered
+types are also instances of DiscreteOrdered.
+
+This approach was suggested by Ben Rudiak-Gould on
+comp.lang.functional.
+
+In theory the Float and Double types should be treated as enumerated
+because they are held in fixed-length data fields, and hence must have
+pairs of values that are adjacent.  However they are treated as
+continuous here for two reasons:
+
+   * The Float and Double types are practical approximations to Real
+     numbers, which are continuous.  Hence it makes sense for Float
+     and Double to pretend to share this property.
+
+   * There is no standard way to determine the adjacency of Float and
+     Double values in Haskell.  "succ 3.0" returns 4.0, which is not
+     appropriate here.
+
+
+Ranges
+------
+
+Module Data.Ranged.Ranges defines the Range type.  A range has a lower and an
+upper Boundary.
+
+Set-like operations are defined on ranges, but they return variable
+numbers of results, and hence return either Maybe Range or [Range].
+
+
+RangedSet
+---------
+
+Module Data.Ranged.RangedSet defines the RSet type.  This is the
+actual ranged set type.  It is constructed from a list of ranges.
+There are two functions to do this:
+
+   * makeRangedSet takes a finite list of ranges that may overlap or be
+     out of order.  It sorts them and merges overlapping ranges using
+     the normaliseRangeList function.
+     
+   * unsafeRangedSet takes a list of ranges that must be in order and not
+     overlapping.  The behaviour of the resulting set is not defined if this
+     precondition is not met.
+     
+In theory the standard QuickCheck generator for RSet could generate an
+arbitrary list of ranges and then normalise them, but in practice this
+tends to produce a very small number of ranges because of the high
+probability of overlaps.  So instead an arbitrary list of boundaries
+is generated and these are then sorted and paired off into
+non-overlapping ranges.
+
+
+Infinite Sets
+-------------
+
+In theory, thanks to lazy evaluation ranged sets can handle infinite
+lists of ranges.  These are known as "infinite sets".  Note that this
+is not the same as a set with a final upper bound of "AboveAll".
+
+Unfortunately there is no simple way to guarantee that computations on
+infinite sets will terminate.  So infinite sets are not supported.
+
+QuickCheck
+----------
+
+All the types in the Ranged Set library are instances of Arbitrary from
+the QuickCheck library, and the source code includes a number of
+important properties for Ranges and RSets defined using QuickCheck.  These 
+can be treated as a formal specification of the properties of these types.
diff --git a/Ranged-sets.cabal b/Ranged-sets.cabal
new file mode 100644
--- /dev/null
+++ b/Ranged-sets.cabal
@@ -0,0 +1,17 @@
+Name:           Ranged-sets
+Version:        0.1.0
+License:        BSD3
+License-file:   LICENSE.txt
+Copyright:      Paul Johnson, 2005, 2006, 2007
+Author:         Paul Johnson
+Homepage:       http://ranged-sets.sourceforge.net/
+Maintainer:     paul@cogito.org.uk
+Stability:      beta
+Category:       Data 
+Build-Depends:  base
+Synopsis:       Ranged sets for Haskell
+Description:	A ranged set is an ordered list of ranges.  This allows sets 
+		such as all reals x such that 
+                (0.25 < x <= 0.75 or 1.4 <= x < 2.3 or 4.5 < x).
+Exposed-modules: Data.Ranged, Data.Ranged.Boundaries, Data.Ranged.Ranges, Data.Ranged.RangedSet
+Extra-source-files: README.txt CHANGES.txt INSTALL.txt TODO.txt Doc/Data-Ranged-Boundaries.html Doc/Data-Ranged.html Doc/Data-Ranged-RangedSet.html Doc/Data-Ranged-Ranges.html Doc/doc-index.html Doc/index.html 
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,6 @@
+
+module Main where
+
+import Distribution.Simple
+
+main = defaultMain
diff --git a/TODO.txt b/TODO.txt
new file mode 100644
--- /dev/null
+++ b/TODO.txt
@@ -0,0 +1,13 @@
+Things to do:
+  
+* Test with yhc.
+
+* Define ranges of times and dates.  The set of all Mondays, for instance,
+  or the set of all second weeks in the month.  Any such functions would
+  have to take a start date because the only alternative is to start
+  with the epoch, and that would not be efficient.  The existing date-time
+  functions look a bit clunky for this job, but the proposals of
+  Ashley Yakeley at http://semantic.org/TimeLib/ look more suitable.
+
+
+  
