Skip to content

Commit

Permalink
change IntegerInterval representation similar to the one of #7
Browse files Browse the repository at this point in the history
  • Loading branch information
msakai committed Oct 12, 2019
1 parent 16796ed commit d6ea96d
Showing 1 changed file with 36 additions and 13 deletions.
49 changes: 36 additions & 13 deletions src/Data/IntegerInterval/Internal.hs
@@ -1,5 +1,5 @@
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE CPP, DeriveDataTypeable #-}
{-# LANGUAGE CPP, DeriveDataTypeable, DeriveGeneric, LambdaCase #-}
{-# LANGUAGE Safe #-}
#if __GLASGOW_HASKELL__ >= 708
{-# LANGUAGE RoleAnnotations #-}
Expand All @@ -17,12 +17,19 @@ import Control.DeepSeq
import Data.Data
import Data.ExtendedReal
import Data.Hashable
import GHC.Generics (Generic)

infix 5 <=..<=

-- | The intervals (/i.e./ connected and convex subsets) over integers (__Z__).
data IntegerInterval = Interval !(Extended Integer) !(Extended Integer)
deriving (Eq, Typeable)
data IntegerInterval
= Whole
| Empty
| Point !Integer
| LessOrEqual !Integer
| GreaterOrEqual !Integer
| Closed !Integer !Integer
deriving (Eq, Generic, Typeable)

-- | Lower endpoint (/i.e./ greatest lower bound) of the interval.
--
Expand All @@ -32,7 +39,13 @@ data IntegerInterval = Interval !(Extended Integer) !(Extended Integer)
--
-- * 'lowerBound' of an interval may or may not be a member of the interval.
lowerBound :: IntegerInterval -> Extended Integer
lowerBound (Interval lb _) = lb
lowerBound = \case
Whole -> NegInf
Empty -> PosInf
Point r -> Finite r
LessOrEqual _ -> NegInf
GreaterOrEqual r -> Finite r
Closed p _ -> Finite p

-- | Upper endpoint (/i.e./ least upper bound) of the interval.
--
Expand All @@ -42,7 +55,13 @@ lowerBound (Interval lb _) = lb
--
-- * 'upperBound' of an interval is a member of the interval.
upperBound :: IntegerInterval -> Extended Integer
upperBound (Interval _ ub) = ub
upperBound = \case
Whole -> PosInf
Empty -> NegInf
Point r -> Finite r
LessOrEqual r -> Finite r
GreaterOrEqual _ -> PosInf
Closed _ p -> Finite p

-- This instance preserves data abstraction at the cost of inefficiency.
-- We provide limited reflection services for the sake of data abstraction.
Expand All @@ -61,11 +80,9 @@ intervalConstr = mkConstr intervalDataType "<=..<=" [] Infix
intervalDataType :: DataType
intervalDataType = mkDataType "Data.IntegerInterval.Internal.IntegerInterval" [intervalConstr]

instance NFData IntegerInterval where
rnf (Interval lb ub) = rnf lb `seq` rnf ub
instance NFData IntegerInterval

instance Hashable IntegerInterval where
hashWithSalt s (Interval lb ub) = s `hashWithSalt` lb `hashWithSalt` ub
instance Hashable IntegerInterval

-- | closed interval [@l@,@u@]
(<=..<=)
Expand All @@ -74,10 +91,16 @@ instance Hashable IntegerInterval where
-> IntegerInterval
(<=..<=) PosInf _ = empty
(<=..<=) _ NegInf = empty
(<=..<=) lb ub
| lb <= ub = Interval lb ub
| otherwise = empty
(<=..<=) NegInf PosInf = Whole
(<=..<=) NegInf (Finite ub) = LessOrEqual ub
(<=..<=) (Finite lb) PosInf = GreaterOrEqual lb
(<=..<=) (Finite lb) (Finite ub) =
case compare lb ub of
EQ -> Point lb
LT -> Closed lb ub
GT -> Empty
{-# INLINE (<=..<=) #-}

-- | empty (contradicting) interval
empty :: IntegerInterval
empty = Interval PosInf NegInf
empty = Empty

0 comments on commit d6ea96d

Please sign in to comment.