module Data.Ranges
(range, ranges, Range, Ranges, inRange, inRanges)
where
newtype Ord a => Range a = Range { unRange :: (a, a) }
newtype Ord a => Ranges a = Ranges [Range a]
range :: (Ord a) => a -> a -> Range a
range l u
| l <= u = Range (l,u)
| otherwise = error "lower bound must be smaller than upper bound"
ranges :: (Ord a) => [(a,a)] -> Ranges a
ranges = Ranges . map Range . foldr (\x xs -> map unRange $ mergeRanges (map Range xs) (uncurry range x)) []
inRange :: (Ord a) => a -> Range a -> Bool
inRange x (Range (l,u)) = x >= l && x <= u
inRanges :: (Ord a) => a -> Ranges a -> Bool
inRanges x (Ranges xs) = or . map (x `inRange`) $ xs
mergeRange :: (Ord a) => Range a -> Range a -> Either (Range a) (Range a)
mergeRange x y
| lx <= uy && ux >= ly ||
ly <= ux && uy >= lx = Right $ Range (min lx ly, max ux uy)
| otherwise = Left $ x
where
(lx,ux) = unRange x
(ly,uy) = unRange y
mergeRanges :: (Ord a) => [Range a] -> Range a -> [Range a]
mergeRanges [] y = [y]
mergeRanges (x:xs) y = case mergeRange x y of
Right z -> mergeRanges xs z
Left x -> x : (mergeRanges xs y)