module Data.Interval
(
Interval(..)
, (...)
, (+/-)
, interval
, empty
, singleton
, symmetric
, hull
, inf
, sup
, width
, valid
, invalid
, isEmpty
, isNonEmpty
, singular
, member
, notMember
, toList
, contains
, isSubsetOf
, adjacent
, mergeable
, overlaps
, (<!)
, (<=!)
, (==!)
, (/=!)
, (>!)
, (>=!)
, (<?)
, (<=?)
, (==?)
, (/=?)
, (>?)
, (>=?)
, (||?)
, (++?)
) where
import Data.Semigroup (Semigroup(..))
data Interval a = I !a !a | Empty
deriving (Eq)
instance (Ord a) => Ord (Interval a) where
compare (I a b) (I x y)
= case compare a x of
EQ -> compare b y
r -> r
instance (Enum a, Ord a) => Semigroup (Interval a) where
(<>) = hull
instance (Enum a, Ord a) => Monoid (Interval a) where
mempty = empty
mappend = (<>)
instance Show a => Show (Interval a) where
showsPrec _ Empty =
showString " Empty "
showsPrec n (I a b) =
showParen (n > 3) $
showsPrec 3 a .
showString " ... " .
showsPrec 3 b
infix 3 ...
infixl 6 +/-
(+/-) :: (Enum a, Num a, Ord a) => a -> a -> Interval a
a +/- b = a b ... a + b
(...) :: (Enum a, Ord a) => a -> a -> Interval a
(...) = I
interval :: (Enum a, Ord a) => a -> a -> Interval a
interval a b
| a <= b = I a b
| otherwise = I b a
empty :: (Enum a, Ord a) => Interval a
empty = Empty
singleton :: (Enum a, Ord a) => a -> Interval a
singleton a = a ... a
symmetric :: (Enum a, Num a, Ord a) => a -> Interval a
symmetric x = negate x ... x
inf :: (Enum a, Ord a) => Interval a -> a
inf (I a _) = a
sup :: (Enum a, Ord a) => Interval a -> a
sup (I _ b) = b
valid :: (Enum a, Ord a) => Interval a -> Bool
valid x = isNonEmpty x && inf x <= sup x
invalid :: (Enum a, Ord a) => Interval a -> Bool
invalid = not . valid
isEmpty :: (Enum a, Ord a) => Interval a -> Bool
isEmpty x = x == Empty
isNonEmpty :: (Enum a, Ord a) => Interval a -> Bool
isNonEmpty = not . isEmpty
singular :: (Enum a, Ord a) => Interval a -> Bool
singular x = valid x && inf x == sup x
width :: (Enum a, Num a, Ord a) => Interval a -> a
width (I a b) = succ $ b a
toList :: (Enum a, Ord a) => Interval a -> [a]
toList (I a b) = [a..b]
member :: (Enum a, Ord a) => a -> Interval a -> Bool
member x (I a b) = x >= a && x <= b
notMember :: (Enum a, Ord a) => a -> Interval a -> Bool
notMember x xs = not (member x xs)
hull :: (Enum a, Ord a) => Interval a -> Interval a -> Interval a
hull x y
| invalid x = y
| invalid y = x
| otherwise = min (inf x) (inf y) ... max (sup x) (sup y)
contains :: (Enum a, Ord a) => Interval a -> Interval a -> Bool
contains x y = (invalid y)
|| (valid x && inf x <= inf y && sup y <= sup x)
isSubsetOf :: (Enum a, Ord a) => Interval a -> Interval a -> Bool
isSubsetOf = flip contains
adjacent :: (Enum a, Ord a) => Interval a -> Interval a -> Bool
adjacent x y = succ (sup x) == inf y || succ (sup y) == inf x
overlaps :: (Enum a, Ord a) => Interval a -> Interval a -> Bool
overlaps = (==?)
mergeable :: (Enum a, Ord a) => Interval a -> Interval a -> Bool
mergeable = (++?)
(<!) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x <! y = sup x < inf y
(<=!) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x <=! y = sup x <= inf y
(==!) :: (Enum a, Eq a, Ord a) => Interval a -> Interval a -> Bool
x ==! y = inf x == inf y && sup x == sup y
(/=!) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x /=! y = sup x < inf y || inf x > sup y
(>!) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x >! y = inf x > sup y
(>=!) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x >=! y = inf x >= sup y
(<?) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x <? y = inf x < sup y
(<=?) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x <=? y = inf x <= sup y
(==?) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x ==? y = inf x <= sup y && sup x >= inf y
(/=?) :: (Enum a, Eq a, Ord a) => Interval a -> Interval a -> Bool
x /=? y = inf x /= sup y || sup x /= inf y
(>?) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x >? y = sup x > inf y
(>=?) ::(Enum a, Ord a)=> Interval a -> Interval a -> Bool
x >=? y = sup x >= inf y
(||?) :: (Enum a, Ord a) => Interval a -> Interval a -> Bool
x ||? y = adjacent x y
(++?) :: (Enum a, Ord a) => Interval a -> Interval a -> Bool
x ++? y = x ||? y || x ==? y