-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprob.hs
77 lines (62 loc) · 1.95 KB
/
prob.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
module Prob where
import Data.Ratio
type Chance = Ratio Int
-- type Prob a = [(a, Chance)]
newtype Prob a = Prob { unProb :: [(a, Chance)]}
always :: a -> Prob a
always a = Prob [(a, 1)]
uniform :: [a] -> Prob a
uniform a = let scale = fromIntegral $ length a
chance = 1 % scale
in Prob $ map (\b -> (b, chance)) a
dice :: Int -> Prob Int
dice n = uniform [1..n]
chanceOf :: (a -> Bool) -> Prob a -> Chance
chanceOf pred (Prob p) = go 0 p
where
go acc [] = acc
go acc (a:as) =
if pred (fst a)
then go (acc + snd a) as
else go acc as
instance Functor Prob where
fmap f (Prob p) = Prob $ fmap (\(e, c) -> (f e, c)) p
instance Applicative Prob where
pure = always
u <*> x = Prob [ (v y, vc * yc)
| (v, vc) <- unProb u
, (y, yc) <- unProb x ]
instance Monad Prob where
m >>= k = Prob . concat $ [ normalize xc $ unProb $ k x
| (x, xc) <- unProb m ]
where
normalize :: Chance -> [(a, Chance)] -> [(a, Chance)]
normalize factor = map (\(a, ac) -> (a, factor * ac))
adventure :: Prob String
adventure = do
strengthSave <- dice 6 -- bear attack
strengthResult <- if strengthSave < 3
then always "survived"
else
do
healCheck <- dice 20
healResult <- if healCheck < 13
then always "survived"
else always "died"
return healResult
return strengthResult
data Door = Prize | NoPrize deriving (Eq)
montyHall :: Prob Door
montyHall = do
firstDoor <- uniform [ Prize, NoPrize, NoPrize ]
-- Monty opens a not-chosen door with no prize behind it
newDoor <- case firstDoor of
Prize -> always NoPrize
NoPrize -> always Prize
return newDoor
main :: IO ()
main = do
putStr "Chance of surviving the adventure: "
putStrLn.show $ chanceOf (=="survived") adventure
putStr "Chance of the prize being behind the new door: "
putStrLn.show $ chanceOf (==Prize) montyHall