module Text.Read.Bounded (
BoundedRead(..),
ReadBounded(..),
readBoundedInteger,
) where
import Data.Int
import Data.Word
import Text.Read (readMaybe)
data BoundedRead a
= NoRead
| ExactRead a
| ClampedRead a
deriving (Show, Read, Eq, Ord)
fromMaybe :: Maybe a -> BoundedRead a
fromMaybe = maybe NoRead ExactRead
data Clamped a
= Exact a
| Clamped a
clamp :: (Bounded a, Integral a) => Integer -> Clamped a
clamp x = if x < minInteger
then Clamped minNum
else if x > maxInteger
then Clamped maxNum
else Exact $ fromInteger x
where
minNum = minBound
maxNum = maxBound
minInteger = toInteger minNum
maxInteger = toInteger maxNum
readBoundedInteger :: (Bounded a, Read a, Integral a) => String -> BoundedRead a
readBoundedInteger str = case readMaybe str of
Nothing -> NoRead
Just x -> case clamp x of
Exact y -> ExactRead y
Clamped y -> ClampedRead y
class ReadBounded a where
readBounded :: String -> BoundedRead a
instance ReadBounded Integer where
readBounded = fromMaybe . readMaybe
instance ReadBounded Int where
readBounded = readBoundedInteger
instance ReadBounded Int8 where
readBounded = readBoundedInteger
instance ReadBounded Int16 where
readBounded = readBoundedInteger
instance ReadBounded Int32 where
readBounded = readBoundedInteger
instance ReadBounded Int64 where
readBounded = readBoundedInteger
instance ReadBounded Word where
readBounded = readBoundedInteger
instance ReadBounded Word8 where
readBounded = readBoundedInteger
instance ReadBounded Word16 where
readBounded = readBoundedInteger
instance ReadBounded Word32 where
readBounded = readBoundedInteger
instance ReadBounded Word64 where
readBounded = readBoundedInteger