module Data.Range
(
Range
, singleton
, range
, member
, notMember
, rangeMin
, rangeMax
, isSingleton
, size
, intersection
, toList
, toAscList
, toDescList
) where
import Data.Semigroup (Semigroup(..))
data Range a = Range
{ _start :: !a
, _end :: !a
} deriving (Eq, Show)
singleton :: a -> Range a
singleton a = Range a a
range :: Ord a => a -> a -> Range a
range start end
| start <= end = Range start end
| otherwise = Range end start
instance Ord a => Semigroup (Range a) where
(<>) (Range start1 end1) (Range start2 end2) =
Range (min start1 start2) (max end1 end2)
stimes n r
| n <= 0 = error "stimes: positive multiplier expected"
| otherwise = r
intersection :: Ord a => Range a -> Range a -> Maybe (Range a)
intersection (Range start1 end1) (Range start2 end2) =
if start > end
then Nothing
else Just (Range start end)
where start = max start1 start2
end = min end1 end2
overlap :: Ord a => Range a -> Range a -> Bool
overlap (Range start1 end1) (Range start2 end2) =
(start1 >= start2 && start1 <= end2) ||
(start2 >= start1 && start2 <= end1)
rangeMin :: Range a -> a
rangeMin (Range a _) = a
rangeMax :: Range a -> a
rangeMax (Range _ a) = a
size :: Num a => Range a -> a
size (Range start end) = end start + 1
isSingleton :: Eq a => Range a -> Bool
isSingleton (Range a b) = a == b
toList :: Enum a => Range a -> [a]
toList (Range start end) = [start..end]
toAscList :: Enum a => Range a -> [a]
toAscList = toList
toDescList :: Enum a => Range a -> [a]
toDescList = reverse . toList
member :: Ord a => a -> Range a -> Bool
member a (Range start end) = a >= start && a <= end
notMember :: Ord a => a -> Range a -> Bool
notMember a = not . member a