{- | We play the following game: We roll a die until we stop or we get three spots. In the first case we own all spots obtained so far, in the latter case we own nothing. What is the strategy for maximizing the expected score? -}moduleNumeric.Probability.Example.DiceAccumwhereimportqualifiedNumeric.Probability.Random asRndimportqualifiedNumeric.Probability.Distribution asDistimportqualifiedNumeric.Probability.Transition asTransimportqualifiedNumeric.Probability.Monad asMonadExtimportNumeric.Probability.Trace (Trace )importNumeric.Probability.Example.Dice (Die ,)typeScore =Intdie ::Fractionalprob =>Dist.T prob Die die :: forall prob. Fractional prob => T prob Score die =forall prob a. Fractional prob => Spread prob a Dist.uniform [Score 1..Score 6]roll ::Fractionalprob =>Trans.T prob (MaybeScore )roll :: forall prob. Fractional prob => T prob (Maybe Score) roll =forall b a. b -> (a -> b) -> Maybe a -> b maybe(forall (m :: * -> *) a. Monad m => a -> m a returnforall a. Maybe a Nothing)(\Score score ->forall a b c. (a -> b -> c) -> b -> a -> c flipforall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapforall prob. Fractional prob => T prob Score die forall a b. (a -> b) -> a -> b $\Score spots ->-- where is my beloved 'toMaybe' ?ifScore spots forall a. Eq a => a -> a -> Bool ==Score 3thenforall a. Maybe a Nothingelseforall a. a -> Maybe a Just(Score score forall a. Num a => a -> a -> a +Score spots ))continue ::Score ->Boolcontinue :: Score -> Bool continue Score scoreInt =letscore :: Rational score =forall a b. (Integral a, Num b) => a -> b fromIntegralScore scoreInt ::Rationalinforall a. Num a => T a a -> a Dist.expected (forall prob a. Fractional prob => Spread prob a Dist.uniform (Rational 0forall a. a -> [a] -> [a] :forall a b. (a -> b) -> [a] -> [b] map(Rational score forall a. Num a => a -> a -> a +)[Rational 1,Rational 2,Rational 4,Rational 5,Rational 6]))forall a. Ord a => a -> a -> Bool >Rational score -- | optimal strategystrategy ::Fractionalprob =>Trans.T prob (MaybeScore )strategy :: forall prob. Fractional prob => T prob (Maybe Score) strategy Maybe Score s0 =forall b a. b -> (a -> b) -> Maybe a -> b maybe(forall (m :: * -> *) a. Monad m => a -> m a returnforall a. Maybe a Nothing)(\Score score ->ifScore -> Bool continue Score score thenforall prob. Fractional prob => T prob (Maybe Score) roll Maybe Score s0 elseforall (m :: * -> *) a. Monad m => a -> m a returnMaybe Score s0 )Maybe Score s0 -- | distribution of the scores that are achieved with the optimal strategygame ::Fractionalprob =>Dist.T prob (MaybeScore )game :: forall prob. Fractional prob => T prob (Maybe Score) game =forall prob a. (Num prob, Ord a) => [T prob a] -> T prob a Trans.compose (forall a. Score -> a -> [a] replicateScore 18forall prob. Fractional prob => T prob (Maybe Score) strategy )(forall a. a -> Maybe a JustScore 0)-- MonadExt.compose (replicate 8 turn) (Just 0){- too inefficient game :: Fractional prob => Dist.T prob Score game = let turn score = if continue score then roll score >>= \s -> if s==0 then return 0 else turn s else return score in turn 0 -}walk ::Int->IO(Trace (MaybeScore ))walk :: Score -> IO (Trace (Maybe Score)) walk Score n =forall a. T a -> IO a Rnd.run forall a b. (a -> b) -> a -> b $forall (m :: * -> *) a. Monad m => Score -> (a -> m a) -> a -> m [a] MonadExt.walk Score n (forall prob a. (Num prob, Ord prob, Random prob) => T prob a -> Change a Rnd.change (forall prob. Fractional prob => T prob (Maybe Score) roll ::Trans.T Double(MaybeScore )))(forall a. a -> Maybe a JustScore 0)