module Data.Monoid.Average (
Average(..),
average,
maybeAverage
) where
import Prelude hiding ((**))
import Data.Typeable
import Data.Maybe
import Data.Semigroup
import Data.AdditiveGroup
import Data.VectorSpace
import Data.AffineSpace
import Control.Monad
import Control.Applicative
newtype Average a = Average { getAverage :: [a] }
deriving (Show, Semigroup, Monoid, Typeable, Functor, Applicative)
instance (Fractional a, Eq a) => Eq (Average a) where
a == b = average a == average b
instance (Fractional a, Ord a) => Ord (Average a) where
a `compare` b = average a `compare` average b
instance Num a => Num (Average a) where
(+) = liftA2 (+)
(*) = liftA2 (*)
negate = fmap negate
abs = fmap abs
signum = fmap signum
fromInteger = pure . fromInteger
instance (Fractional a, Num a) => Fractional (Average a) where
(/) = liftA2 (/)
fromRational = pure . fromRational
instance (Real a, Fractional a) => Real (Average a) where
toRational = toRational . average
instance Floating a => Floating (Average a) where
pi = pure pi
exp = fmap exp
sqrt = fmap sqrt
log = fmap log
sin = fmap sin
tan = fmap tan
cos = fmap cos
asin = fmap asin
atan = fmap atan
acos = fmap acos
sinh = fmap sinh
tanh = fmap tanh
cosh = fmap cosh
asinh = fmap asinh
atanh = fmap atanh
acosh = fmap acosh
instance AdditiveGroup a => AdditiveGroup (Average a) where
zeroV = pure zeroV
(^+^) = liftA2 (^+^)
negateV = fmap negateV
instance VectorSpace a => VectorSpace (Average a) where
type Scalar (Average a) = Scalar a
s *^ v = liftA2 (*^) (pure s) v
instance AffineSpace a => AffineSpace (Average a) where
type Diff (Average a) = Average (Diff a)
p1 .-. p2 = liftA2 (.-.) p1 p2
p .+^ v = liftA2 (.+^) p v
average :: Fractional a => Average a -> a
average = fromMaybe 0 . maybeAverage
maybeAverage :: Fractional a => Average a -> Maybe a
maybeAverage (Average []) = Nothing
maybeAverage (Average xs) = Just $ sum xs / fromIntegral (length xs)