cdar-mBound-0.1.0.0: src/Data/CDAR/Extended.hs
{- |The Extended module allows real-valued numeric data types to be extended by
positive and negative infinity.
-}
{-# LANGUAGE DeriveFunctor #-}
module Data.CDAR.Extended (Extended(..)) where
import Control.Monad
-- |Extended numbers are either finite numbers or one of the two infinities.
data Extended a = PosInf | NegInf | Finite a deriving (Eq,Read,Show,Functor)
instance Applicative Extended where
pure = Finite
(Finite f) <*> (Finite x) = Finite $ f x
(Finite _) <*> PosInf = PosInf
(Finite _) <*> NegInf = NegInf
PosInf <*> _ = PosInf
NegInf <*> _ = NegInf
instance Monad Extended where
return = pure
(Finite x) >>= f = f x
PosInf >>= _ = PosInf
NegInf >>= _ = NegInf
instance Ord a => Ord (Extended a) where
compare PosInf PosInf = EQ
compare NegInf NegInf = EQ
compare _ PosInf = LT
compare NegInf _ = LT
compare PosInf _ = GT
compare _ NegInf = GT
compare (Finite a) (Finite b) = compare a b
instance (Ord a, Num a) => Num (Extended a) where
-- PosInf + NegInf should be undefined, but here it is the first argument
(+) = liftM2 (+)
-- 0 * ???Inf should be undefined, but here it is PosInf
a * PosInf = if a < 0 then NegInf else PosInf
PosInf * a = if a < 0 then NegInf else PosInf
a * NegInf = if a < 0 then PosInf else NegInf
NegInf * a = if a < 0 then PosInf else NegInf
a * b = (*) <$> a <*> b
negate = fmap negate
abs = fmap abs
signum PosInf = Finite 1
signum NegInf = Finite (-1)
signum a = signum <$> a
fromInteger i = Finite $ fromInteger i
instance Real a => Real (Extended a) where
toRational (Finite x) = toRational x
toRational _ = undefined