module MontyHall where
import Probability
(Dist, Trans, RDist, uniform, mapD, (~.), idT, sequ, certainly, )
--import ListUtils (replicate)
import List ( (\\) )
-- import Monad (liftM)
data Door = A | B | C
deriving (Eq,Ord,Show)
doors :: [Door]
doors = [A,B,C]
data State = Doors {prize :: Door, chosen :: Door, opened :: Door}
deriving (Eq,Ord,Show)
-- | initial configuration of the game status
start :: State
start = Doors {prize=u,chosen=u,opened=u} where u=undefined
{- |
Steps of the game:
(1) hide the prize
(2) choose a door
(3) open a non-open door, not revealing the prize
(4) apply strategy: switch or stay
-}
hide :: Trans State
hide s = uniform [s {prize = d} | d <- doors]
choose :: Trans State
choose s = uniform [s {chosen = d} | d <- doors]
open :: Trans State
open s = uniform [s {opened = d} | d <- doors \\ [prize s,chosen s]]
type Strategy = Trans State
switch :: Strategy
switch s = uniform [s {chosen = d} | d <- doors \\ [chosen s,opened s]]
stay :: Strategy
stay = idT
game :: Strategy -> Trans State
game s = sequ [hide,choose,open,s]
-- * Playing the game
data Outcome = Win | Lose
deriving (Eq,Ord,Show)
result :: State -> Outcome
result s = if chosen s==prize s then Win else Lose
eval :: Strategy -> Dist Outcome
eval s = mapD result (game s start)
simEval :: Int -> Strategy -> RDist Outcome
simEval k s = mapD result `fmap` (k ~. game s) start
-- * Alternative modeling
firstChoice :: Dist Outcome
firstChoice = uniform [Win,Lose,Lose]
switch' :: Trans Outcome
switch' Win = certainly Lose
switch' Lose = certainly Win