Prob.hs 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. module Rolling.Prob where
  2. import GHC.Exts (groupWith)
  3. -- a probability expressed as a ratio (i.e. @P 1 2@ is a 50/50 chance)
  4. data P = P Int Int deriving (Eq, Ord)
  5. instance Show P where
  6. show (P n t) = show n ++ " in " ++ show t
  7. times :: P -> P -> P
  8. P a at `times` P b bt = P (a * b) (at * bt)
  9. combine :: [P] -> P
  10. combine ps =
  11. let tots = [ t | P _ t <- ps ]
  12. newTot = foldr lcm 1 tots
  13. newNums = [ if t == newTot then n else error "FIXME" | P n t <- ps ]
  14. in P (sum newNums) newTot
  15. -- a Prob monad that tracks possible things with their probabilities
  16. newtype Prob a = Prob { unprob :: [(a, P)] } deriving (Eq, Show)
  17. instance Functor Prob where
  18. fmap f (Prob xs) = Prob [(f x, p) | (x, p) <- xs]
  19. instance Applicative Prob where
  20. pure x = Prob [(x, P 1 1)]
  21. Prob fs <*> Prob xs = Prob [(f x, pf `times` px) | (f, pf) <- fs, (x, px) <- xs]
  22. instance Monad Prob where
  23. Prob xs >>= f =
  24. Prob [ (y, p `times` p')
  25. | (x, p) <- xs
  26. , (y, p') <- unprob (f x)
  27. ]
  28. -- probably the wrong name? this is collapsing identical possibilities
  29. -- into one
  30. normalize :: (Ord a) => Prob a -> Prob a
  31. normalize (Prob xs) =
  32. Prob [(fst (head rs), combine (map snd rs)) | rs <- groupWith fst xs ]