module Data.Number.Interval(Interval, ival, getIval) where
data Interval a = I a a
ival :: (Ord a) => a -> a -> Interval a
ival l h | l <= h = I l h
| otherwise = error "Interval.ival: low > high"
getIval :: Interval a -> (a, a)
getIval (I l h) = (l, h)
instance (Ord a) => Eq (Interval a) where
I l h == I l' h' = l == h' && h == l'
I l h /= I l' h' = h < l' || h' < l
instance (Ord a) => Ord (Interval a) where
I l h < I l' h' = h < l'
I l h <= I l' h' = h <= l'
I l h > I l' h' = l > h'
I l h >= I l' h' = l >= h'
compare _ _ = error "Interval compare"
max _ _ = error "Interval max"
min _ _ = error "Interval min"
instance (Eq a, Show a) => Show (Interval a) where
showsPrec p (I l h) | l == h = showsPrec p l
| otherwise = showsPrec p l . showString ".." . showsPrec p h
instance (Ord a, Num a) => Num (Interval a) where
I l h + I l' h' = I (l + l') (h + h')
I l h I l' h' = I (l h') (h l')
I l h * I l' h' = I (minimum xs) (maximum xs) where xs = [l*l', l*h', h*l', h*h']
negate (I l h) = I (h) (l)
abs _ = error "Interval abs"
signum _ = error "Interval signum"
fromInteger i = I l l where l = fromInteger i
instance (Ord a, Fractional a) => Fractional (Interval a) where
I l h / I l' h' | signum l' == signum h' && l' /= 0 = I (minimum xs) (maximum xs)
| otherwise = error "Interval: division by 0"
where xs = [l/l', l/h', h/l', h/h']
fromRational r = I l l where l = fromRational r