{-# LANGUAGE Safe #-}
{-# LANGUAGE DeriveGeneric #-}

-- | The Data module for common data types within the code.
module Data.Range.Data where

import Control.DeepSeq (NFData)
import GHC.Generics (Generic)

data OverlapType = Separate | Overlap | Adjoin
   deriving (OverlapType -> OverlapType -> Bool
(OverlapType -> OverlapType -> Bool)
-> (OverlapType -> OverlapType -> Bool) -> Eq OverlapType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: OverlapType -> OverlapType -> Bool
== :: OverlapType -> OverlapType -> Bool
$c/= :: OverlapType -> OverlapType -> Bool
/= :: OverlapType -> OverlapType -> Bool
Eq, Int -> OverlapType -> ShowS
[OverlapType] -> ShowS
OverlapType -> String
(Int -> OverlapType -> ShowS)
-> (OverlapType -> String)
-> ([OverlapType] -> ShowS)
-> Show OverlapType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> OverlapType -> ShowS
showsPrec :: Int -> OverlapType -> ShowS
$cshow :: OverlapType -> String
show :: OverlapType -> String
$cshowList :: [OverlapType] -> ShowS
showList :: [OverlapType] -> ShowS
Show, (forall x. OverlapType -> Rep OverlapType x)
-> (forall x. Rep OverlapType x -> OverlapType)
-> Generic OverlapType
forall x. Rep OverlapType x -> OverlapType
forall x. OverlapType -> Rep OverlapType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. OverlapType -> Rep OverlapType x
from :: forall x. OverlapType -> Rep OverlapType x
$cto :: forall x. Rep OverlapType x -> OverlapType
to :: forall x. Rep OverlapType x -> OverlapType
Generic)

instance NFData OverlapType

-- | Represents a type of boundary.
data BoundType
   = Inclusive -- ^ The value at the boundary should be included in the bound.
   | Exclusive -- ^ The value at the boundary should be excluded in the bound.
   deriving (BoundType -> BoundType -> Bool
(BoundType -> BoundType -> Bool)
-> (BoundType -> BoundType -> Bool) -> Eq BoundType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BoundType -> BoundType -> Bool
== :: BoundType -> BoundType -> Bool
$c/= :: BoundType -> BoundType -> Bool
/= :: BoundType -> BoundType -> Bool
Eq, Eq BoundType
Eq BoundType =>
(BoundType -> BoundType -> Ordering)
-> (BoundType -> BoundType -> Bool)
-> (BoundType -> BoundType -> Bool)
-> (BoundType -> BoundType -> Bool)
-> (BoundType -> BoundType -> Bool)
-> (BoundType -> BoundType -> BoundType)
-> (BoundType -> BoundType -> BoundType)
-> Ord BoundType
BoundType -> BoundType -> Bool
BoundType -> BoundType -> Ordering
BoundType -> BoundType -> BoundType
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: BoundType -> BoundType -> Ordering
compare :: BoundType -> BoundType -> Ordering
$c< :: BoundType -> BoundType -> Bool
< :: BoundType -> BoundType -> Bool
$c<= :: BoundType -> BoundType -> Bool
<= :: BoundType -> BoundType -> Bool
$c> :: BoundType -> BoundType -> Bool
> :: BoundType -> BoundType -> Bool
$c>= :: BoundType -> BoundType -> Bool
>= :: BoundType -> BoundType -> Bool
$cmax :: BoundType -> BoundType -> BoundType
max :: BoundType -> BoundType -> BoundType
$cmin :: BoundType -> BoundType -> BoundType
min :: BoundType -> BoundType -> BoundType
Ord, Int -> BoundType -> ShowS
[BoundType] -> ShowS
BoundType -> String
(Int -> BoundType -> ShowS)
-> (BoundType -> String)
-> ([BoundType] -> ShowS)
-> Show BoundType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BoundType -> ShowS
showsPrec :: Int -> BoundType -> ShowS
$cshow :: BoundType -> String
show :: BoundType -> String
$cshowList :: [BoundType] -> ShowS
showList :: [BoundType] -> ShowS
Show, (forall x. BoundType -> Rep BoundType x)
-> (forall x. Rep BoundType x -> BoundType) -> Generic BoundType
forall x. Rep BoundType x -> BoundType
forall x. BoundType -> Rep BoundType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. BoundType -> Rep BoundType x
from :: forall x. BoundType -> Rep BoundType x
$cto :: forall x. Rep BoundType x -> BoundType
to :: forall x. Rep BoundType x -> BoundType
Generic)

instance NFData BoundType

-- | Represents a bound at a particular value with a 'BoundType'.
-- There is no implicit understanding if this is a lower or upper bound, it could be either.
data Bound a = Bound
   { forall a. Bound a -> a
boundValue :: a          -- ^ The value at the edge of this bound.
   , forall a. Bound a -> BoundType
boundType :: BoundType   -- ^ The type of bound. Should be 'Inclusive' or 'Exclusive'.
   } deriving (Bound a -> Bound a -> Bool
(Bound a -> Bound a -> Bool)
-> (Bound a -> Bound a -> Bool) -> Eq (Bound a)
forall a. Eq a => Bound a -> Bound a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Bound a -> Bound a -> Bool
== :: Bound a -> Bound a -> Bool
$c/= :: forall a. Eq a => Bound a -> Bound a -> Bool
/= :: Bound a -> Bound a -> Bool
Eq, Eq (Bound a)
Eq (Bound a) =>
(Bound a -> Bound a -> Ordering)
-> (Bound a -> Bound a -> Bool)
-> (Bound a -> Bound a -> Bool)
-> (Bound a -> Bound a -> Bool)
-> (Bound a -> Bound a -> Bool)
-> (Bound a -> Bound a -> Bound a)
-> (Bound a -> Bound a -> Bound a)
-> Ord (Bound a)
Bound a -> Bound a -> Bool
Bound a -> Bound a -> Ordering
Bound a -> Bound a -> Bound a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Bound a)
forall a. Ord a => Bound a -> Bound a -> Bool
forall a. Ord a => Bound a -> Bound a -> Ordering
forall a. Ord a => Bound a -> Bound a -> Bound a
$ccompare :: forall a. Ord a => Bound a -> Bound a -> Ordering
compare :: Bound a -> Bound a -> Ordering
$c< :: forall a. Ord a => Bound a -> Bound a -> Bool
< :: Bound a -> Bound a -> Bool
$c<= :: forall a. Ord a => Bound a -> Bound a -> Bool
<= :: Bound a -> Bound a -> Bool
$c> :: forall a. Ord a => Bound a -> Bound a -> Bool
> :: Bound a -> Bound a -> Bool
$c>= :: forall a. Ord a => Bound a -> Bound a -> Bool
>= :: Bound a -> Bound a -> Bool
$cmax :: forall a. Ord a => Bound a -> Bound a -> Bound a
max :: Bound a -> Bound a -> Bound a
$cmin :: forall a. Ord a => Bound a -> Bound a -> Bound a
min :: Bound a -> Bound a -> Bound a
Ord, Int -> Bound a -> ShowS
[Bound a] -> ShowS
Bound a -> String
(Int -> Bound a -> ShowS)
-> (Bound a -> String) -> ([Bound a] -> ShowS) -> Show (Bound a)
forall a. Show a => Int -> Bound a -> ShowS
forall a. Show a => [Bound a] -> ShowS
forall a. Show a => Bound a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Bound a -> ShowS
showsPrec :: Int -> Bound a -> ShowS
$cshow :: forall a. Show a => Bound a -> String
show :: Bound a -> String
$cshowList :: forall a. Show a => [Bound a] -> ShowS
showList :: [Bound a] -> ShowS
Show, (forall x. Bound a -> Rep (Bound a) x)
-> (forall x. Rep (Bound a) x -> Bound a) -> Generic (Bound a)
forall x. Rep (Bound a) x -> Bound a
forall x. Bound a -> Rep (Bound a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Bound a) x -> Bound a
forall a x. Bound a -> Rep (Bound a) x
$cfrom :: forall a x. Bound a -> Rep (Bound a) x
from :: forall x. Bound a -> Rep (Bound a) x
$cto :: forall a x. Rep (Bound a) x -> Bound a
to :: forall x. Rep (Bound a) x -> Bound a
Generic)

instance NFData a => NFData (Bound a)

instance Functor Bound where
   fmap :: forall a b. (a -> b) -> Bound a -> Bound b
fmap a -> b
f (Bound a
v BoundType
vType) = b -> BoundType -> Bound b
forall a. a -> BoundType -> Bound a
Bound (a -> b
f a
v) BoundType
vType

-- TODO can we implement Monoid for Range a with the addition of an empty?
-- Or maybe we can implement Monoid for a list of ranges...

-- | The Range Data structure; it is capable of representing any type of range. This is
-- the primary data structure in this library. Everything should be possible to convert
-- back into this datatype. All ranges in this structure are inclusively bound.
data Range a
   = SingletonRange a               -- ^ Represents a single element as a range. @SingletonRange a@ is equivalent to @SpanRange (Bound a Inclusive) (Bound a Inclusive)@.
   | SpanRange (Bound a) (Bound a)  -- ^ Represents a bounded span of elements. The first argument is expected to be less than or equal to the second argument.
   | LowerBoundRange (Bound a)      -- ^ Represents a range with a finite lower bound and an infinite upper bound.
   | UpperBoundRange (Bound a)      -- ^ Represents a range with an infinite lower bound and a finite upper bound.
   | InfiniteRange                  -- ^ Represents an infinite range over all values.
   deriving (Range a -> Range a -> Bool
(Range a -> Range a -> Bool)
-> (Range a -> Range a -> Bool) -> Eq (Range a)
forall a. Eq a => Range a -> Range a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Range a -> Range a -> Bool
== :: Range a -> Range a -> Bool
$c/= :: forall a. Eq a => Range a -> Range a -> Bool
/= :: Range a -> Range a -> Bool
Eq, (forall x. Range a -> Rep (Range a) x)
-> (forall x. Rep (Range a) x -> Range a) -> Generic (Range a)
forall x. Rep (Range a) x -> Range a
forall x. Range a -> Rep (Range a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Range a) x -> Range a
forall a x. Range a -> Rep (Range a) x
$cfrom :: forall a x. Range a -> Rep (Range a) x
from :: forall x. Range a -> Rep (Range a) x
$cto :: forall a x. Rep (Range a) x -> Range a
to :: forall x. Rep (Range a) x -> Range a
Generic)

instance NFData a => NFData (Range a)

instance Show a => Show (Range a) where
   showsPrec :: Int -> Range a -> ShowS
showsPrec Int
i (SingletonRange a
a) = (String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
"SingletonRange ") ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
i a
a
   showsPrec Int
i (SpanRange (Bound a
l BoundType
lType) (Bound a
r BoundType
rType)) =
      Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
i a
l ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BoundType -> BoundType -> ShowS
showSymbol BoundType
lType BoundType
rType ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
i a
r
      where
         showSymbol :: BoundType -> BoundType -> ShowS
showSymbol BoundType
Inclusive BoundType
Inclusive = String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
" +=+ "
         showSymbol BoundType
Inclusive BoundType
Exclusive = String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
" +=* "
         showSymbol BoundType
Exclusive BoundType
Inclusive = String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
" *=+ "
         showSymbol BoundType
Exclusive BoundType
Exclusive = String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
" *=* "
   showsPrec Int
i (LowerBoundRange (Bound a
a BoundType
Inclusive)) = (String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
"lbi ") ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
i a
a)
   showsPrec Int
i (LowerBoundRange (Bound a
a BoundType
Exclusive)) = (String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
"lbe ") ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
i a
a)
   showsPrec Int
i (UpperBoundRange (Bound a
a BoundType
Inclusive)) = (String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
"ubi ") ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
i a
a)
   showsPrec Int
i (UpperBoundRange (Bound a
a BoundType
Exclusive)) = (String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
"ube ") ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
i a
a)
   showsPrec Int
_ (Range a
InfiniteRange) = String -> ShowS
forall a. [a] -> [a] -> [a]
(++) String
"inf"