module Data.Attoparsec.Number ( Number(..) ) where
import Control.DeepSeq (NFData(rnf))
import Data.Data (Data)
import Data.Function (on)
import Data.Typeable (Typeable)
data Number = I !Integer
| D !Double
deriving (Typeable, Data)
instance Show Number where
show (I a) = show a
show (D a) = show a
instance NFData Number where
rnf (I _) = ()
rnf (D _) = ()
binop :: (Integer -> Integer -> a) -> (Double -> Double -> a)
-> Number -> Number -> a
binop _ d (D a) (D b) = d a b
binop i _ (I a) (I b) = i a b
binop _ d (D a) (I b) = d a (fromIntegral b)
binop _ d (I a) (D b) = d (fromIntegral a) b
instance Eq Number where
(==) = binop (==) (==)
(/=) = binop (/=) (/=)
instance Ord Number where
(<) = binop (<) (<)
(<=) = binop (<=) (<=)
(>) = binop (>) (>)
(>=) = binop (>=) (>=)
compare = binop compare compare
instance Num Number where
(+) = binop (((I$!).) . (+)) (((D$!).) . (+))
() = binop (((I$!).) . ()) (((D$!).) . ())
(*) = binop (((I$!).) . (*)) (((D$!).) . (*))
abs (I a) = I $! abs a
abs (D a) = D $! abs a
negate (I a) = I $! negate a
negate (D a) = D $! negate a
signum (I a) = I $! signum a
signum (D a) = D $! signum a
fromInteger = (I$!) . fromInteger
instance Real Number where
toRational (I a) = fromIntegral a
toRational (D a) = toRational a
instance Fractional Number where
fromRational = (D$!) . fromRational
(/) = binop (((D$!).) . (/) `on` fromIntegral)
(((D$!).) . (/))
recip (I a) = D $! recip (fromIntegral a)
recip (D a) = D $! recip a
instance RealFrac Number where
properFraction (I a) = (fromIntegral a,0)
properFraction (D a) = case properFraction a of
(i,d) -> (i,D d)
truncate (I a) = fromIntegral a
truncate (D a) = truncate a
round (I a) = fromIntegral a
round (D a) = round a
ceiling (I a) = fromIntegral a
ceiling (D a) = ceiling a
floor (I a) = fromIntegral a
floor (D a) = floor a