{-# LANGUAGE RankNTypes #-}
module PSNum where
import Types
data PSNum
= PSInt Integer
| PSReal Double
deriving (Eq, Show)
toPSNum :: Object -> Endsay PSNum
toPSNum (OInteger n) = return (PSInt n)
toPSNum (OReal n) = return (PSReal n)
toPSNum _ = error ".."
fromPSNum :: PSNum -> Object
fromPSNum (PSInt n) = OInteger n
fromPSNum (PSReal n) = OReal n
promoteNum :: (forall a. Num a => a -> a -> a) -> PSNum -> PSNum -> PSNum
promoteNum op (PSInt x) (PSInt y) = PSInt (x `op` y)
promoteNum op (PSInt x) (PSReal y) = PSReal (fromIntegral x `op` y)
promoteNum op (PSReal x) (PSInt y) = PSReal (x `op` fromIntegral y)
promoteNum op (PSReal x) (PSReal y) = PSReal (x `op` y)
resNum :: (forall a. (Num a, Ord a) => a -> a -> b) -> PSNum -> PSNum -> b
resNum op (PSInt x) (PSInt y) = (x `op` y)
resNum op (PSInt x) (PSReal y) = (fromIntegral x `op` y)
resNum op (PSReal x) (PSInt y) = (x `op` fromIntegral y)
resNum op (PSReal x) (PSReal y) = (x `op` y)
overNum :: (forall a. Num a => a -> a) -> PSNum -> PSNum
overNum op (PSInt x) = PSInt (op x)
overNum op (PSReal x) = PSReal (op x)
instance Num PSNum where
(+) = promoteNum (+)
(-) = promoteNum (-)
(*) = promoteNum (*)
negate = overNum negate
abs = overNum abs
signum = overNum signum
fromInteger = PSInt
instance Ord PSNum where
compare = resNum compare