module ParsedInteger (ParsedInteger, parseWithBounds, parsedToInteger, IntegerBoundError (..))
where

newtype ParsedInteger = ParsedInteger Integer

data IntegerBoundError = IntegerOutOfBounds deriving (Int -> IntegerBoundError -> ShowS
[IntegerBoundError] -> ShowS
IntegerBoundError -> String
(Int -> IntegerBoundError -> ShowS)
-> (IntegerBoundError -> String)
-> ([IntegerBoundError] -> ShowS)
-> Show IntegerBoundError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> IntegerBoundError -> ShowS
showsPrec :: Int -> IntegerBoundError -> ShowS
$cshow :: IntegerBoundError -> String
show :: IntegerBoundError -> String
$cshowList :: [IntegerBoundError] -> ShowS
showList :: [IntegerBoundError] -> ShowS
Show)

parseWithBounds :: Maybe Integer -> Maybe Integer -> Integer -> Either IntegerBoundError ParsedInteger
parseWithBounds :: Maybe Integer
-> Maybe Integer
-> Integer
-> Either IntegerBoundError ParsedInteger
parseWithBounds (Just Integer
lowerBoundInclusive) (Just Integer
upperBoundInclusive) Integer
n =
    if Integer
lowerBoundInclusive Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
n Bool -> Bool -> Bool
&& Integer
upperBoundInclusive Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
n
        then ParsedInteger -> Either IntegerBoundError ParsedInteger
forall a. a -> Either IntegerBoundError a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ParsedInteger -> Either IntegerBoundError ParsedInteger)
-> ParsedInteger -> Either IntegerBoundError ParsedInteger
forall a b. (a -> b) -> a -> b
$ Integer -> ParsedInteger
ParsedInteger Integer
n
        else IntegerBoundError -> Either IntegerBoundError ParsedInteger
forall a b. a -> Either a b
Left IntegerBoundError
IntegerOutOfBounds
parseWithBounds (Just Integer
lowerBoundInclusive) Maybe Integer
Nothing Integer
n =
    if Integer
lowerBoundInclusive Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
n
        then ParsedInteger -> Either IntegerBoundError ParsedInteger
forall a. a -> Either IntegerBoundError a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ParsedInteger -> Either IntegerBoundError ParsedInteger)
-> ParsedInteger -> Either IntegerBoundError ParsedInteger
forall a b. (a -> b) -> a -> b
$ Integer -> ParsedInteger
ParsedInteger Integer
n
        else IntegerBoundError -> Either IntegerBoundError ParsedInteger
forall a b. a -> Either a b
Left IntegerBoundError
IntegerOutOfBounds
parseWithBounds Maybe Integer
Nothing (Just Integer
upperBoundInclusive) Integer
n =
    if Integer
upperBoundInclusive Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
n
        then ParsedInteger -> Either IntegerBoundError ParsedInteger
forall a. a -> Either IntegerBoundError a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ParsedInteger -> Either IntegerBoundError ParsedInteger)
-> ParsedInteger -> Either IntegerBoundError ParsedInteger
forall a b. (a -> b) -> a -> b
$ Integer -> ParsedInteger
ParsedInteger Integer
n
        else IntegerBoundError -> Either IntegerBoundError ParsedInteger
forall a b. a -> Either a b
Left IntegerBoundError
IntegerOutOfBounds
parseWithBounds Maybe Integer
Nothing Maybe Integer
Nothing Integer
n = ParsedInteger -> Either IntegerBoundError ParsedInteger
forall a b. b -> Either a b
Right (ParsedInteger -> Either IntegerBoundError ParsedInteger)
-> ParsedInteger -> Either IntegerBoundError ParsedInteger
forall a b. (a -> b) -> a -> b
$ Integer -> ParsedInteger
ParsedInteger Integer
n

parsedToInteger :: ParsedInteger -> Integer
parsedToInteger :: ParsedInteger -> Integer
parsedToInteger (ParsedInteger Integer
n) = Integer
n