module Data.Interval
(
Interval(..)
, (...)
, (+/-)
, interval
, empty
, singleton
, symmetric
, hull
, inf
, sup
, width
, valid
, invalid
, isEmpty
, singular
, member
, notMember
, toList
, IOrdering(..), cmp, cmp'
, contains
, isSubsetOf
, adjacent
, (<!)
, (<=!)
, (==!)
, (/=!)
, (>!)
, (>=!)
, (<?)
, (<=?)
, (==?)
, (/=?)
, (>?)
, (>=?)
) where
import Data.IOrdering (IOrdering(..))
import Data.Semigroup (Semigroup(..))
data Interval a = I !a !a | Empty
deriving (Eq, Ord)
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
inf :: (Enum a, Ord a) => Interval a -> a
inf (I a _) = a
sup :: (Enum a, Ord a) => Interval a -> a
sup (I _ b) = b
cmp :: (Enum a, Ord a) => Interval a -> Interval a -> IOrdering
cmp x y
| x ==! y = E
| x <! y = L
| x >! y = G
| x <=! y = ONeg
| x >=! y = OPos
cmp' :: (Enum a, Ord a) => Interval a -> Interval a -> Interval a -> IOrdering
cmp' x y z = (cmp y x) <> (cmp y z)
valid :: (Enum a, Ord a) => Interval a -> Bool
valid 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
singular :: (Enum a, Ord a) => Interval a -> Bool
singular x = valid x && inf x == sup x
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 || isEmpty x) = y
| (invalid y || isEmpty 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
(<!) ::(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
width :: (Enum a, Num a, Ord a) => Interval a -> a
width (I a b) = succ $ b a
symmetric :: (Enum a, Num a, Ord a) => a -> Interval a
symmetric x = negate x ... x