{- | Number type based on Float with formatting in percents. -} module Numeric.Probability.Percentage where import qualified Numeric.Probability.Distribution as Dist import qualified Numeric.Probability.Random as Rnd import Numeric.Probability.Show (showR) import Numeric.Probability.Trace (Trace) import qualified System.Random as Random -- ** Probabilities newtype T = Cons Float deriving (Eq, Ord) percent :: Float -> T percent x = Cons (x/100) showPfix :: (RealFrac prob, Show prob) => Int -> prob -> String showPfix precision f = if precision==0 then showR 3 (round (f*100) :: Integer)++"%" else showR (4+precision) (roundRel precision (f*100))++"%" roundRel :: (RealFrac a) => Int -> a -> a roundRel p x = let d = 10^p in fromIntegral (round (x*d) :: Integer)/d -- -- mixed precision -- -- -- showP :: ProbRep -> String -- showP f | f>=0.1 = showR 3 (round (f*100))++"%" -- | otherwise = show (f*100)++"%" -- fixed precision -- -- showP :: ProbRep -> String -- showP = showPfix 1 instance Show T where show (Cons p) = showPfix 1 p infix 0 // {- | Print distribution as table with configurable precision. -} (//) :: (Ord a, Show a) => Dist a -> Int -> IO () (//) x prec = putStr (Dist.pretty (\(Cons p) -> showPfix prec p) x) liftP :: (Float -> Float) -> T -> T liftP f (Cons x) = Cons (f x) liftP2 :: (Float -> Float -> Float) -> T -> T -> T liftP2 f (Cons x) (Cons y) = Cons (f x y) instance Num T where fromInteger = Cons . fromInteger (+) = liftP2 (+) (-) = liftP2 (-) (*) = liftP2 (*) abs = liftP abs signum = liftP signum negate = liftP negate instance Fractional T where fromRational = Cons . fromRational recip = liftP recip (/) = liftP2 (/) instance Floating T where pi = Cons pi exp = liftP exp sqrt = liftP sqrt log = liftP log (**) = liftP2 (**) logBase = liftP2 logBase sin = liftP sin tan = liftP tan cos = liftP cos asin = liftP asin atan = liftP atan acos = liftP acos sinh = liftP sinh tanh = liftP tanh cosh = liftP cosh asinh = liftP asinh atanh = liftP atanh acosh = liftP acosh instance Random.Random T where randomR (Cons l, Cons r) = (\(x,g) -> (Cons x, g)) . Random.randomR (l,r) random = (\(x,g) -> (Cons x, g)) . Random.random randomRIO (Cons l, Cons r) = fmap Cons $ Random.randomRIO (l,r) randomIO = fmap Cons $ Random.randomIO type Dist a = Dist.T T a type Spread a = [a] -> Dist a type RDist a = Rnd.T (Dist a) type Trans a = a -> Dist a type Space a = Trace (Dist a) type Expand a = a -> Space a type RTrans a = a -> RDist a type RSpace a = Rnd.T (Space a) type RExpand a = a -> RSpace a