module Numeric.Probability.Expectation where

import qualified Numeric.Probability.Distribution as Dist
import qualified Numeric.Probability.Percentage as Probability

-- TO DO: generalize Float to arbitrary Num type
--
class ToFloat a where
  toFloat :: a -> Float

instance ToFloat Float   where toFloat :: Float -> Float
toFloat = forall a. a -> a
id
instance ToFloat Int     where toFloat :: Int -> Float
toFloat = forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance ToFloat Integer where toFloat :: Integer -> Float
toFloat = forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance ToFloat Probability.T
                         where toFloat :: T -> Float
toFloat (Probability.Cons Float
x) = Float
x

class FromFloat a where
  fromFloat :: Float -> a

instance FromFloat Float   where fromFloat :: Float -> Float
fromFloat = forall a. a -> a
id
instance FromFloat Int     where fromFloat :: Float -> Int
fromFloat = forall a b. (RealFrac a, Integral b) => a -> b
round
instance FromFloat Integer where fromFloat :: Float -> Integer
fromFloat = forall a b. (RealFrac a, Integral b) => a -> b
round

-- expected :: ToFloat a => Prob.Dist a -> Float
-- expected = sum . map (\(x,p)->toFloat x*p) . Dist.decons

class Expected a where
  expected :: a -> Float

-- instance ToFloat a => Expected a where
--   expected = toFloat
instance Expected Float   where expected :: Float -> Float
expected = forall a. a -> a
id
instance Expected Int     where expected :: Int -> Float
expected = forall a. ToFloat a => a -> Float
toFloat
instance Expected Integer where expected :: Integer -> Float
expected = forall a. ToFloat a => a -> Float
toFloat

instance Expected a => Expected [a] where
  expected :: [a] -> Float
expected = forall a. Num a => T a a -> a
Dist.expected forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall prob a. Fractional prob => Spread prob a
Dist.uniform forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a. Expected a => a -> Float
expected
--  expected xs = sum (map expected xs) / toFloat (length xs)

floatDist :: (ToFloat prob, Expected a) =>
   Dist.T prob a -> Dist.T Float Float
floatDist :: forall prob a.
(ToFloat prob, Expected a) =>
T prob a -> T Float Float
floatDist =
   forall prob a. [(a, prob)] -> T prob a
Dist.Cons forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   forall a b. (a -> b) -> [a] -> [b]
map (\(a
x,prob
p) -> (forall a. Expected a => a -> Float
expected a
x, forall a. ToFloat a => a -> Float
toFloat prob
p)) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   forall prob a. T prob a -> [(a, prob)]
Dist.decons

instance (ToFloat prob, Expected a) => Expected (Dist.T prob a) where
  expected :: T prob a -> Float
expected = forall a. Num a => T a a -> a
Dist.expected forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall prob a.
(ToFloat prob, Expected a) =>
T prob a -> T Float Float
floatDist
--  expected = Dist.expected . fmap expected


-- | statistical analyses
variance :: Expected a => Probability.Dist a -> Float
variance :: forall a. Expected a => Dist a -> Float
variance = forall a. Num a => T a a -> a
Dist.variance forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall prob a.
(ToFloat prob, Expected a) =>
T prob a -> T Float Float
floatDist

stdDev :: Expected a => Probability.Dist a -> Float
stdDev :: forall a. Expected a => Dist a -> Float
stdDev = forall a. Floating a => a -> a
sqrt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Expected a => Dist a -> Float
variance