misc/haskell/exs/Prob.hs

67 lines
1.3 KiB
Haskell
Raw Normal View History

2018-08-05 18:53:07 +02:00
#!/usr/bin/env nix-script
#!>haskell
{- Learn you a Haskell exercise -}
module Data.Probability
( Event, Prob
, flatten
, onProb
, sumCheck
, probs
, group
) where
import Data.Ratio
import Data.Function (on)
import Data.List (groupBy)
import Control.Monad (ap)
import Control.Applicative
type Event a = (Rational, a)
newtype Prob a = Prob { getProb :: [Event a] }
instance Show a => Show (Prob a) where
show (Prob xs) = show xs
instance Functor Prob where
fmap f (Prob xs) = Prob $ map (fmap f) xs
instance Applicative Prob where
pure = return
(<*>) = ap
instance Monad Prob where
return x = Prob [(1, x)]
m >>= f = flatten $ f <$> m
fail _ = Prob []
-- Flatten nested probabilities by one level
flatten :: Prob (Prob a) -> Prob a
flatten = onProb $ concat . map (uncurry multBy)
where multBy p = map (\(r,x) -> (p*r,x)) . getProb
-- Raise a function to work on the Prob newtype
onProb :: ([Event a] -> [Event b]) -> (Prob a -> Prob b)
onProb f = Prob . f . getProb
-- Get the probabily of every event
probs :: Prob a -> [Rational]
probs = map fst . getProb
-- Check whether the 1-norm of the probability is 1
sumCheck :: Prob a -> Bool
sumCheck x = sum (probs x) == 1
-- Group events with the same outcome
group :: Eq a => Prob a -> Prob a
group = onProb $ map head . groupBy ((==) `on` snd)