{-# LANGUAGE DeriveAnyClass       #-}
{-# LANGUAGE MonoLocalBinds       #-}
{-# LANGUAGE NoImplicitPrelude    #-}
{-# LANGUAGE TemplateHaskell      #-}
{-# LANGUAGE UndecidableInstances #-}

{-# OPTIONS_GHC -fno-omit-interface-pragmas #-}
{-# OPTIONS_GHC -fno-specialise #-}
{-# OPTIONS_GHC -fno-ignore-interface-pragmas #-}

-- | A type for intervals and associated functions.
module PlutusLedgerApi.V1.Interval
    ( Interval(..)
    , UpperBound(..)
    , LowerBound(..)
    , Extended(..)
    , Closure
    , member
    , interval
    , from
    , to
    , always
    , never
    , singleton
    , hull
    , intersection
    , overlaps
    , contains
    , isEmpty
    , before
    , after
    , lowerBound
    , upperBound
    , strictLowerBound
    , strictUpperBound
    ) where

import Control.DeepSeq (NFData)
import GHC.Generics (Generic)
import Prelude qualified as Haskell
import Prettyprinter (Pretty (pretty), comma, (<+>))

import PlutusTx qualified
import PlutusTx.Lift (makeLift)
import PlutusTx.Prelude

-- | An interval of @a@s.
--
--   The interval may be either closed or open at either end, meaning
--   that the endpoints may or may not be included in the interval.
--
--   The interval can also be unbounded on either side.
data Interval a = Interval { forall a. Interval a -> LowerBound a
ivFrom :: LowerBound a, forall a. Interval a -> UpperBound a
ivTo :: UpperBound a }
    deriving stock (Interval a -> Interval a -> Closure
forall a. Eq a => Interval a -> Interval a -> Closure
forall a. (a -> a -> Closure) -> (a -> a -> Closure) -> Eq a
/= :: Interval a -> Interval a -> Closure
$c/= :: forall a. Eq a => Interval a -> Interval a -> Closure
== :: Interval a -> Interval a -> Closure
$c== :: forall a. Eq a => Interval a -> Interval a -> Closure
Haskell.Eq, Interval a -> Interval a -> Closure
Interval a -> Interval a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (Interval a)
forall a. Ord a => Interval a -> Interval a -> Closure
forall a. Ord a => Interval a -> Interval a -> Ordering
forall a. Ord a => Interval a -> Interval a -> Interval a
min :: Interval a -> Interval a -> Interval a
$cmin :: forall a. Ord a => Interval a -> Interval a -> Interval a
max :: Interval a -> Interval a -> Interval a
$cmax :: forall a. Ord a => Interval a -> Interval a -> Interval a
>= :: Interval a -> Interval a -> Closure
$c>= :: forall a. Ord a => Interval a -> Interval a -> Closure
> :: Interval a -> Interval a -> Closure
$c> :: forall a. Ord a => Interval a -> Interval a -> Closure
<= :: Interval a -> Interval a -> Closure
$c<= :: forall a. Ord a => Interval a -> Interval a -> Closure
< :: Interval a -> Interval a -> Closure
$c< :: forall a. Ord a => Interval a -> Interval a -> Closure
compare :: Interval a -> Interval a -> Ordering
$ccompare :: forall a. Ord a => Interval a -> Interval a -> Ordering
Haskell.Ord, Int -> Interval a -> ShowS
forall a. Show a => Int -> Interval a -> ShowS
forall a. Show a => [Interval a] -> ShowS
forall a. Show a => Interval a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Interval a] -> ShowS
$cshowList :: forall a. Show a => [Interval a] -> ShowS
show :: Interval a -> String
$cshow :: forall a. Show a => Interval a -> String
showsPrec :: Int -> Interval a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Interval a -> ShowS
Haskell.Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Interval a) x -> Interval a
forall a x. Interval a -> Rep (Interval a) x
$cto :: forall a x. Rep (Interval a) x -> Interval a
$cfrom :: forall a x. Interval a -> Rep (Interval a) x
Generic)
    deriving anyclass (forall a. NFData a => Interval a -> ()
forall a. (a -> ()) -> NFData a
rnf :: Interval a -> ()
$crnf :: forall a. NFData a => Interval a -> ()
NFData)

instance Functor Interval where
  fmap :: forall a b. (a -> b) -> Interval a -> Interval b
fmap a -> b
f (Interval LowerBound a
from UpperBound a
to) = forall a. LowerBound a -> UpperBound a -> Interval a
Interval (a -> b
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LowerBound a
from) (a -> b
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> UpperBound a
to)

instance Pretty a => Pretty (Interval a) where
    pretty :: forall ann. Interval a -> Doc ann
pretty (Interval LowerBound a
l UpperBound a
h) = forall a ann. Pretty a => a -> Doc ann
pretty LowerBound a
l forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall ann. Doc ann
comma forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall a ann. Pretty a => a -> Doc ann
pretty UpperBound a
h

-- | A set extended with a positive and negative infinity.
data Extended a = NegInf | Finite a | PosInf
    deriving stock (Extended a -> Extended a -> Closure
forall a. Eq a => Extended a -> Extended a -> Closure
forall a. (a -> a -> Closure) -> (a -> a -> Closure) -> Eq a
/= :: Extended a -> Extended a -> Closure
$c/= :: forall a. Eq a => Extended a -> Extended a -> Closure
== :: Extended a -> Extended a -> Closure
$c== :: forall a. Eq a => Extended a -> Extended a -> Closure
Haskell.Eq, Extended a -> Extended a -> Closure
Extended a -> Extended a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (Extended a)
forall a. Ord a => Extended a -> Extended a -> Closure
forall a. Ord a => Extended a -> Extended a -> Ordering
forall a. Ord a => Extended a -> Extended a -> Extended a
min :: Extended a -> Extended a -> Extended a
$cmin :: forall a. Ord a => Extended a -> Extended a -> Extended a
max :: Extended a -> Extended a -> Extended a
$cmax :: forall a. Ord a => Extended a -> Extended a -> Extended a
>= :: Extended a -> Extended a -> Closure
$c>= :: forall a. Ord a => Extended a -> Extended a -> Closure
> :: Extended a -> Extended a -> Closure
$c> :: forall a. Ord a => Extended a -> Extended a -> Closure
<= :: Extended a -> Extended a -> Closure
$c<= :: forall a. Ord a => Extended a -> Extended a -> Closure
< :: Extended a -> Extended a -> Closure
$c< :: forall a. Ord a => Extended a -> Extended a -> Closure
compare :: Extended a -> Extended a -> Ordering
$ccompare :: forall a. Ord a => Extended a -> Extended a -> Ordering
Haskell.Ord, Int -> Extended a -> ShowS
forall a. Show a => Int -> Extended a -> ShowS
forall a. Show a => [Extended a] -> ShowS
forall a. Show a => Extended a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Extended a] -> ShowS
$cshowList :: forall a. Show a => [Extended a] -> ShowS
show :: Extended a -> String
$cshow :: forall a. Show a => Extended a -> String
showsPrec :: Int -> Extended a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Extended a -> ShowS
Haskell.Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Extended a) x -> Extended a
forall a x. Extended a -> Rep (Extended a) x
$cto :: forall a x. Rep (Extended a) x -> Extended a
$cfrom :: forall a x. Extended a -> Rep (Extended a) x
Generic)
    deriving anyclass (forall a. NFData a => Extended a -> ()
forall a. (a -> ()) -> NFData a
rnf :: Extended a -> ()
$crnf :: forall a. NFData a => Extended a -> ()
NFData)

instance Functor Extended where
  fmap :: forall a b. (a -> b) -> Extended a -> Extended b
fmap a -> b
_ Extended a
NegInf     = forall a. Extended a
NegInf
  fmap a -> b
f (Finite a
a) = forall a. a -> Extended a
Finite (a -> b
f a
a)
  fmap a -> b
_ Extended a
PosInf     = forall a. Extended a
PosInf

instance Pretty a => Pretty (Extended a) where
    pretty :: forall ann. Extended a -> Doc ann
pretty Extended a
NegInf     = forall a ann. Pretty a => a -> Doc ann
pretty String
"-∞"
    pretty Extended a
PosInf     = forall a ann. Pretty a => a -> Doc ann
pretty String
"+∞"
    pretty (Finite a
a) = forall a ann. Pretty a => a -> Doc ann
pretty a
a

-- | Whether a bound is inclusive or not.
type Closure = Bool

-- | The upper bound of an interval.
data UpperBound a = UpperBound (Extended a) Closure
    deriving stock (UpperBound a -> UpperBound a -> Closure
forall a. Eq a => UpperBound a -> UpperBound a -> Closure
forall a. (a -> a -> Closure) -> (a -> a -> Closure) -> Eq a
/= :: UpperBound a -> UpperBound a -> Closure
$c/= :: forall a. Eq a => UpperBound a -> UpperBound a -> Closure
== :: UpperBound a -> UpperBound a -> Closure
$c== :: forall a. Eq a => UpperBound a -> UpperBound a -> Closure
Haskell.Eq, UpperBound a -> UpperBound a -> Closure
UpperBound a -> UpperBound a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (UpperBound a)
forall a. Ord a => UpperBound a -> UpperBound a -> Closure
forall a. Ord a => UpperBound a -> UpperBound a -> Ordering
forall a. Ord a => UpperBound a -> UpperBound a -> UpperBound a
min :: UpperBound a -> UpperBound a -> UpperBound a
$cmin :: forall a. Ord a => UpperBound a -> UpperBound a -> UpperBound a
max :: UpperBound a -> UpperBound a -> UpperBound a
$cmax :: forall a. Ord a => UpperBound a -> UpperBound a -> UpperBound a
>= :: UpperBound a -> UpperBound a -> Closure
$c>= :: forall a. Ord a => UpperBound a -> UpperBound a -> Closure
> :: UpperBound a -> UpperBound a -> Closure
$c> :: forall a. Ord a => UpperBound a -> UpperBound a -> Closure
<= :: UpperBound a -> UpperBound a -> Closure
$c<= :: forall a. Ord a => UpperBound a -> UpperBound a -> Closure
< :: UpperBound a -> UpperBound a -> Closure
$c< :: forall a. Ord a => UpperBound a -> UpperBound a -> Closure
compare :: UpperBound a -> UpperBound a -> Ordering
$ccompare :: forall a. Ord a => UpperBound a -> UpperBound a -> Ordering
Haskell.Ord, Int -> UpperBound a -> ShowS
forall a. Show a => Int -> UpperBound a -> ShowS
forall a. Show a => [UpperBound a] -> ShowS
forall a. Show a => UpperBound a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UpperBound a] -> ShowS
$cshowList :: forall a. Show a => [UpperBound a] -> ShowS
show :: UpperBound a -> String
$cshow :: forall a. Show a => UpperBound a -> String
showsPrec :: Int -> UpperBound a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> UpperBound a -> ShowS
Haskell.Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (UpperBound a) x -> UpperBound a
forall a x. UpperBound a -> Rep (UpperBound a) x
$cto :: forall a x. Rep (UpperBound a) x -> UpperBound a
$cfrom :: forall a x. UpperBound a -> Rep (UpperBound a) x
Generic)
    deriving anyclass (forall a. NFData a => UpperBound a -> ()
forall a. (a -> ()) -> NFData a
rnf :: UpperBound a -> ()
$crnf :: forall a. NFData a => UpperBound a -> ()
NFData)

instance Functor UpperBound where
  fmap :: forall a b. (a -> b) -> UpperBound a -> UpperBound b
fmap a -> b
f (UpperBound Extended a
e Closure
c) = forall a. Extended a -> Closure -> UpperBound a
UpperBound (a -> b
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Extended a
e) Closure
c

instance Pretty a => Pretty (UpperBound a) where
    pretty :: forall ann. UpperBound a -> Doc ann
pretty (UpperBound Extended a
PosInf Closure
_) = forall a ann. Pretty a => a -> Doc ann
pretty String
"+∞)"
    pretty (UpperBound Extended a
NegInf Closure
_) = forall a ann. Pretty a => a -> Doc ann
pretty String
"-∞)"
    pretty (UpperBound Extended a
a Closure
True)   = forall a ann. Pretty a => a -> Doc ann
pretty Extended a
a forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall a ann. Pretty a => a -> Doc ann
pretty String
"]"
    pretty (UpperBound Extended a
a Closure
False)  = forall a ann. Pretty a => a -> Doc ann
pretty Extended a
a forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall a ann. Pretty a => a -> Doc ann
pretty String
")"

-- | The lower bound of an interval.
data LowerBound a = LowerBound (Extended a) Closure
    deriving stock (LowerBound a -> LowerBound a -> Closure
forall a. Eq a => LowerBound a -> LowerBound a -> Closure
forall a. (a -> a -> Closure) -> (a -> a -> Closure) -> Eq a
/= :: LowerBound a -> LowerBound a -> Closure
$c/= :: forall a. Eq a => LowerBound a -> LowerBound a -> Closure
== :: LowerBound a -> LowerBound a -> Closure
$c== :: forall a. Eq a => LowerBound a -> LowerBound a -> Closure
Haskell.Eq, LowerBound a -> LowerBound a -> Closure
LowerBound a -> LowerBound a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> Closure)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (LowerBound a)
forall a. Ord a => LowerBound a -> LowerBound a -> Closure
forall a. Ord a => LowerBound a -> LowerBound a -> Ordering
forall a. Ord a => LowerBound a -> LowerBound a -> LowerBound a
min :: LowerBound a -> LowerBound a -> LowerBound a
$cmin :: forall a. Ord a => LowerBound a -> LowerBound a -> LowerBound a
max :: LowerBound a -> LowerBound a -> LowerBound a
$cmax :: forall a. Ord a => LowerBound a -> LowerBound a -> LowerBound a
>= :: LowerBound a -> LowerBound a -> Closure
$c>= :: forall a. Ord a => LowerBound a -> LowerBound a -> Closure
> :: LowerBound a -> LowerBound a -> Closure
$c> :: forall a. Ord a => LowerBound a -> LowerBound a -> Closure
<= :: LowerBound a -> LowerBound a -> Closure
$c<= :: forall a. Ord a => LowerBound a -> LowerBound a -> Closure
< :: LowerBound a -> LowerBound a -> Closure
$c< :: forall a. Ord a => LowerBound a -> LowerBound a -> Closure
compare :: LowerBound a -> LowerBound a -> Ordering
$ccompare :: forall a. Ord a => LowerBound a -> LowerBound a -> Ordering
Haskell.Ord, Int -> LowerBound a -> ShowS
forall a. Show a => Int -> LowerBound a -> ShowS
forall a. Show a => [LowerBound a] -> ShowS
forall a. Show a => LowerBound a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LowerBound a] -> ShowS
$cshowList :: forall a. Show a => [LowerBound a] -> ShowS
show :: LowerBound a -> String
$cshow :: forall a. Show a => LowerBound a -> String
showsPrec :: Int -> LowerBound a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> LowerBound a -> ShowS
Haskell.Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (LowerBound a) x -> LowerBound a
forall a x. LowerBound a -> Rep (LowerBound a) x
$cto :: forall a x. Rep (LowerBound a) x -> LowerBound a
$cfrom :: forall a x. LowerBound a -> Rep (LowerBound a) x
Generic)
    deriving anyclass (forall a. NFData a => LowerBound a -> ()
forall a. (a -> ()) -> NFData a
rnf :: LowerBound a -> ()
$crnf :: forall a. NFData a => LowerBound a -> ()
NFData)

instance Functor LowerBound where
  fmap :: forall a b. (a -> b) -> LowerBound a -> LowerBound b
fmap a -> b
f (LowerBound Extended a
e Closure
c) = forall a. Extended a -> Closure -> LowerBound a
LowerBound (a -> b
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Extended a
e) Closure
c

instance Pretty a => Pretty (LowerBound a) where
    pretty :: forall ann. LowerBound a -> Doc ann
pretty (LowerBound Extended a
PosInf Closure
_) = forall a ann. Pretty a => a -> Doc ann
pretty String
"(+∞"
    pretty (LowerBound Extended a
NegInf Closure
_) = forall a ann. Pretty a => a -> Doc ann
pretty String
"(-∞"
    pretty (LowerBound Extended a
a Closure
True)   = forall a ann. Pretty a => a -> Doc ann
pretty String
"[" forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall a ann. Pretty a => a -> Doc ann
pretty Extended a
a
    pretty (LowerBound Extended a
a Closure
False)  = forall a ann. Pretty a => a -> Doc ann
pretty String
"(" forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall a ann. Pretty a => a -> Doc ann
pretty Extended a
a

PlutusTx.makeIsDataIndexed ''Extended [('NegInf,0),('Finite,1),('PosInf,2)]
PlutusTx.makeIsDataIndexed ''UpperBound [('UpperBound,0)]
PlutusTx.makeIsDataIndexed ''LowerBound [('LowerBound,0)]
PlutusTx.makeIsDataIndexed ''Interval [('Interval,0)]

makeLift ''Extended
makeLift ''LowerBound
makeLift ''UpperBound
makeLift ''Interval

instance Eq a => Eq (Extended a) where
    {-# INLINABLE (==) #-}
    Extended a
NegInf   == :: Extended a -> Extended a -> Closure
== Extended a
NegInf   = Closure
True
    Extended a
PosInf   == Extended a
PosInf   = Closure
True
    Finite a
l == Finite a
r = a
l forall a. Eq a => a -> a -> Closure
== a
r
    Extended a
_        == Extended a
_        = Closure
False

instance Ord a => Ord (Extended a) where
    {-# INLINABLE compare #-}
    Extended a
NegInf   compare :: Extended a -> Extended a -> Ordering
`compare` Extended a
NegInf   = Ordering
EQ
    Extended a
NegInf   `compare` Extended a
_        = Ordering
LT
    Extended a
_        `compare` Extended a
NegInf   = Ordering
GT
    Extended a
PosInf   `compare` Extended a
PosInf   = Ordering
EQ
    Extended a
_        `compare` Extended a
PosInf   = Ordering
LT
    Extended a
PosInf   `compare` Extended a
_        = Ordering
GT
    Finite a
l `compare` Finite a
r = a
l forall a. Ord a => a -> a -> Ordering
`compare` a
r

instance Eq a => Eq (UpperBound a) where
    {-# INLINABLE (==) #-}
    UpperBound Extended a
v1 Closure
in1 == :: UpperBound a -> UpperBound a -> Closure
== UpperBound Extended a
v2 Closure
in2 = Extended a
v1 forall a. Eq a => a -> a -> Closure
== Extended a
v2 Closure -> Closure -> Closure
&& Closure
in1 forall a. Eq a => a -> a -> Closure
== Closure
in2

instance Ord a => Ord (UpperBound a) where
    {-# INLINABLE compare #-}
    UpperBound Extended a
v1 Closure
in1 compare :: UpperBound a -> UpperBound a -> Ordering
`compare` UpperBound Extended a
v2 Closure
in2 = case Extended a
v1 forall a. Ord a => a -> a -> Ordering
`compare` Extended a
v2 of
        Ordering
LT -> Ordering
LT
        Ordering
GT -> Ordering
GT
        -- A closed upper bound is bigger than an open upper bound. This corresponds
        -- to the normal order on Bool.
        Ordering
EQ -> Closure
in1 forall a. Ord a => a -> a -> Ordering
`compare` Closure
in2

instance Eq a => Eq (LowerBound a) where
    {-# INLINABLE (==) #-}
    LowerBound Extended a
v1 Closure
in1 == :: LowerBound a -> LowerBound a -> Closure
== LowerBound Extended a
v2 Closure
in2 = Extended a
v1 forall a. Eq a => a -> a -> Closure
== Extended a
v2 Closure -> Closure -> Closure
&& Closure
in1 forall a. Eq a => a -> a -> Closure
== Closure
in2

instance Ord a => Ord (LowerBound a) where
    {-# INLINABLE compare #-}
    LowerBound Extended a
v1 Closure
in1 compare :: LowerBound a -> LowerBound a -> Ordering
`compare` LowerBound Extended a
v2 Closure
in2 = case Extended a
v1 forall a. Ord a => a -> a -> Ordering
`compare` Extended a
v2 of
        Ordering
LT -> Ordering
LT
        Ordering
GT -> Ordering
GT
        -- An open lower bound is bigger than a closed lower bound. This corresponds
        -- to the *reverse* of the normal order on Bool.
        Ordering
EQ -> Closure
in2 forall a. Ord a => a -> a -> Ordering
`compare` Closure
in1

{-# INLINABLE strictUpperBound #-}
strictUpperBound :: a -> UpperBound a
strictUpperBound :: forall a. a -> UpperBound a
strictUpperBound a
a = forall a. Extended a -> Closure -> UpperBound a
UpperBound (forall a. a -> Extended a
Finite a
a) Closure
False

{-# INLINABLE strictLowerBound #-}
strictLowerBound :: a -> LowerBound a
strictLowerBound :: forall a. a -> LowerBound a
strictLowerBound a
a = forall a. Extended a -> Closure -> LowerBound a
LowerBound (forall a. a -> Extended a
Finite a
a) Closure
False

{-# INLINABLE lowerBound #-}
lowerBound :: a -> LowerBound a
lowerBound :: forall a. a -> LowerBound a
lowerBound a
a = forall a. Extended a -> Closure -> LowerBound a
LowerBound (forall a. a -> Extended a
Finite a
a) Closure
True

{-# INLINABLE upperBound #-}
upperBound :: a -> UpperBound a
upperBound :: forall a. a -> UpperBound a
upperBound a
a = forall a. Extended a -> Closure -> UpperBound a
UpperBound (forall a. a -> Extended a
Finite a
a) Closure
True

instance Ord a => JoinSemiLattice (Interval a) where
    {-# INLINABLE (\/) #-}
    \/ :: Interval a -> Interval a -> Interval a
(\/) = forall a. Ord a => Interval a -> Interval a -> Interval a
hull

instance Ord a => BoundedJoinSemiLattice (Interval a) where
    {-# INLINABLE bottom #-}
    bottom :: Interval a
bottom = forall a. Interval a
never

instance Ord a => MeetSemiLattice (Interval a) where
    {-# INLINABLE (/\) #-}
    /\ :: Interval a -> Interval a -> Interval a
(/\) = forall a. Ord a => Interval a -> Interval a -> Interval a
intersection

instance Ord a => BoundedMeetSemiLattice (Interval a) where
    {-# INLINABLE top #-}
    top :: Interval a
top = forall a. Interval a
always

instance Eq a => Eq (Interval a) where
    {-# INLINABLE (==) #-}
    Interval a
l == :: Interval a -> Interval a -> Closure
== Interval a
r = forall a. Interval a -> LowerBound a
ivFrom Interval a
l forall a. Eq a => a -> a -> Closure
== forall a. Interval a -> LowerBound a
ivFrom Interval a
r Closure -> Closure -> Closure
&& forall a. Interval a -> UpperBound a
ivTo Interval a
l forall a. Eq a => a -> a -> Closure
== forall a. Interval a -> UpperBound a
ivTo Interval a
r

{-# INLINABLE interval #-}
-- | @interval a b@ includes all values that are greater than or equal to @a@
-- and smaller than or equal to @b@. Therefore it includes @a@ and @b@.
interval :: a -> a -> Interval a
interval :: forall a. a -> a -> Interval a
interval a
s a
s' = forall a. LowerBound a -> UpperBound a -> Interval a
Interval (forall a. a -> LowerBound a
lowerBound a
s) (forall a. a -> UpperBound a
upperBound a
s')

{-# INLINABLE singleton #-}
singleton :: a -> Interval a
singleton :: forall a. a -> Interval a
singleton a
s = forall a. a -> a -> Interval a
interval a
s a
s

{-# INLINABLE from #-}
-- | @from a@ is an 'Interval' that includes all values that are
--  greater than or equal to @a@.
from :: a -> Interval a
from :: forall a. a -> Interval a
from a
s = forall a. LowerBound a -> UpperBound a -> Interval a
Interval (forall a. a -> LowerBound a
lowerBound a
s) (forall a. Extended a -> Closure -> UpperBound a
UpperBound forall a. Extended a
PosInf Closure
True)

{-# INLINABLE to #-}
-- | @to a@ is an 'Interval' that includes all values that are
--  smaller than or equal to @a@.
to :: a -> Interval a
to :: forall a. a -> Interval a
to a
s = forall a. LowerBound a -> UpperBound a -> Interval a
Interval (forall a. Extended a -> Closure -> LowerBound a
LowerBound forall a. Extended a
NegInf Closure
True) (forall a. a -> UpperBound a
upperBound a
s)

{-# INLINABLE always #-}
-- | An 'Interval' that covers every slot.
always :: Interval a
always :: forall a. Interval a
always = forall a. LowerBound a -> UpperBound a -> Interval a
Interval (forall a. Extended a -> Closure -> LowerBound a
LowerBound forall a. Extended a
NegInf Closure
True) (forall a. Extended a -> Closure -> UpperBound a
UpperBound forall a. Extended a
PosInf Closure
True)

{-# INLINABLE never #-}
-- | An 'Interval' that is empty.
never :: Interval a
never :: forall a. Interval a
never = forall a. LowerBound a -> UpperBound a -> Interval a
Interval (forall a. Extended a -> Closure -> LowerBound a
LowerBound forall a. Extended a
PosInf Closure
True) (forall a. Extended a -> Closure -> UpperBound a
UpperBound forall a. Extended a
NegInf Closure
True)

{-# INLINABLE member #-}
-- | Check whether a value is in an interval.
member :: Ord a => a -> Interval a -> Bool
member :: forall a. Ord a => a -> Interval a -> Closure
member a
a Interval a
i = Interval a
i forall a. Ord a => Interval a -> Interval a -> Closure
`contains` forall a. a -> Interval a
singleton a
a

{-# INLINABLE overlaps #-}
-- | Check whether two intervals overlap, that is, whether there is a value that
--   is a member of both intervals.
overlaps :: (Enum a, Ord a) => Interval a -> Interval a -> Bool
overlaps :: forall a. (Enum a, Ord a) => Interval a -> Interval a -> Closure
overlaps Interval a
l Interval a
r = Closure -> Closure
not forall a b. (a -> b) -> a -> b
$ forall a. (Enum a, Ord a) => Interval a -> Closure
isEmpty (Interval a
l forall a. Ord a => Interval a -> Interval a -> Interval a
`intersection` Interval a
r)

{-# INLINABLE intersection #-}
-- | 'intersection a b' is the largest interval that is contained in 'a' and in
--   'b', if it exists.
intersection :: Ord a => Interval a -> Interval a -> Interval a
intersection :: forall a. Ord a => Interval a -> Interval a -> Interval a
intersection (Interval LowerBound a
l1 UpperBound a
h1) (Interval LowerBound a
l2 UpperBound a
h2) = forall a. LowerBound a -> UpperBound a -> Interval a
Interval (forall a. Ord a => a -> a -> a
max LowerBound a
l1 LowerBound a
l2) (forall a. Ord a => a -> a -> a
min UpperBound a
h1 UpperBound a
h2)

{-# INLINABLE hull #-}
-- | 'hull a b' is the smallest interval containing 'a' and 'b'.
hull :: Ord a => Interval a -> Interval a -> Interval a
hull :: forall a. Ord a => Interval a -> Interval a -> Interval a
hull (Interval LowerBound a
l1 UpperBound a
h1) (Interval LowerBound a
l2 UpperBound a
h2) = forall a. LowerBound a -> UpperBound a -> Interval a
Interval (forall a. Ord a => a -> a -> a
min LowerBound a
l1 LowerBound a
l2) (forall a. Ord a => a -> a -> a
max UpperBound a
h1 UpperBound a
h2)

{-# INLINABLE contains #-}
-- | @a `contains` b@ is true if the 'Interval' @b@ is entirely contained in
--   @a@. That is, @a `contains` b@ if for every entry @s@, if @member s b@ then
--   @member s a@.
contains :: Ord a => Interval a -> Interval a -> Bool
contains :: forall a. Ord a => Interval a -> Interval a -> Closure
contains (Interval LowerBound a
l1 UpperBound a
h1) (Interval LowerBound a
l2 UpperBound a
h2) = LowerBound a
l1 forall a. Ord a => a -> a -> Closure
<= LowerBound a
l2 Closure -> Closure -> Closure
&& UpperBound a
h2 forall a. Ord a => a -> a -> Closure
<= UpperBound a
h1

{-# INLINABLE isEmpty #-}
-- | Check if an 'Interval' is empty.
isEmpty :: (Enum a, Ord a) => Interval a -> Bool
isEmpty :: forall a. (Enum a, Ord a) => Interval a -> Closure
isEmpty (Interval (LowerBound Extended a
v1 Closure
in1) (UpperBound Extended a
v2 Closure
in2)) = case Extended a
v1 forall a. Ord a => a -> a -> Ordering
`compare` Extended a
v2 of
    Ordering
LT -> if Closure
openInterval then forall {a}. (Ord a, Enum a) => Extended a -> Extended a -> Closure
checkEnds Extended a
v1 Extended a
v2 else Closure
False
    Ordering
GT -> Closure
True
    Ordering
EQ -> Closure -> Closure
not (Closure
in1 Closure -> Closure -> Closure
&& Closure
in2)
    where
        openInterval :: Closure
openInterval = Closure
in1 forall a. Eq a => a -> a -> Closure
== Closure
False Closure -> Closure -> Closure
&& Closure
in2 forall a. Eq a => a -> a -> Closure
== Closure
False
        -- | We check two finite ends to figure out if there are elements between them.
        -- If there are no elements then the interval is empty (#3467).
        checkEnds :: Extended a -> Extended a -> Closure
checkEnds (Finite a
v1') (Finite a
v2') = (forall a. Enum a => a -> a
succ a
v1') forall a. Ord a => a -> a -> Ordering
`compare` a
v2' forall a. Eq a => a -> a -> Closure
== Ordering
EQ
        checkEnds Extended a
_ Extended a
_                       = Closure
False

{-# INLINABLE before #-}
-- | Check if a value is earlier than the beginning of an 'Interval'.
before :: Ord a => a -> Interval a -> Bool
before :: forall a. Ord a => a -> Interval a -> Closure
before a
h (Interval LowerBound a
f UpperBound a
_) = forall a. a -> LowerBound a
lowerBound a
h forall a. Ord a => a -> a -> Closure
< LowerBound a
f

{-# INLINABLE after #-}
-- | Check if a value is later than the end of a 'Interval'.
after :: Ord a => a -> Interval a -> Bool
after :: forall a. Ord a => a -> Interval a -> Closure
after a
h (Interval LowerBound a
_ UpperBound a
t) = forall a. a -> UpperBound a
upperBound a
h forall a. Ord a => a -> a -> Closure
> UpperBound a
t