{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE Safe #-}
module Data.Connection.Interval (
Interval()
, imap
, (...)
, empty
, singleton
, contains
, endpts
, upper
, lower
, interval
) where
import safe Data.Bifunctor (bimap)
import safe Data.Connection.Type
import safe Data.Lattice
import safe Data.Order
import safe Prelude hiding (Ord(..), Eq(..), Bounded, until)
import safe qualified Data.Eq as Eq
data Interval a = Empty | I !a !a deriving Show
instance Eq a => Eq (Interval a) where
Empty == Empty = True
Empty == _ = False
_ == Empty = False
I x y == I x' y' = x == x' && y == y'
instance Preorder a => Preorder (Interval a) where
Empty <~ _ = True
_ <~ Empty = False
I x y <~ I x' y' = x' <~ x && y <~ y'
imap :: Preorder b => (a -> b) -> Interval a -> Interval b
imap f = maybe empty (uncurry (...)) . fmap (bimap f f) . endpts
infix 3 ...
(...) :: Preorder a => a -> a -> Interval a
x ... y
| x <~ y = I x y
| otherwise = Empty
{-# INLINE (...) #-}
empty :: Interval a
empty = Empty
{-# INLINE empty #-}
singleton :: a -> Interval a
singleton a = I a a
{-# INLINE singleton #-}
endpts :: Interval a -> Maybe (a, a)
endpts Empty = Nothing
endpts (I x y) = Just (x, y)
{-# INLINE endpts #-}
contains :: Preorder a => Interval a -> a -> Bool
contains Empty _ = False
contains (I x y) p = x <~ p && p <~ y
upper :: UpperBounded a => a -> Interval a
upper x = x ... top
{-# INLINE upper #-}
lower :: LowerBounded a => a -> Interval a
lower x = bottom ... x
{-# INLINE lower #-}
interval :: Bounded a => Trip (Interval a) a
interval = Trip f g h where
f = maybe bottom (uncurry (\/)) . endpts
g = singleton
h = maybe top (uncurry (/\)) . endpts