```{- |
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?
-}
module Numeric.Probability.Example.DiceAccum where

import qualified Numeric.Probability.Example.Dice as Dice
import qualified Numeric.Probability.Random as Rnd
import qualified Numeric.Probability.Distribution as Dist
import qualified Numeric.Probability.Transition as Trans
import Numeric.Probability.Trace (Trace)

import Numeric.Probability.Example.Dice (Die, )

type Score = Int

die :: Fractional prob => Dist.T prob Die
die = Dist.uniform [1..6]

roll :: Fractional prob => Trans.T prob (Maybe Score)
roll =
maybe
(return Nothing)
(\score -> flip fmap die \$
\spots ->
-- where is my beloved 'toMaybe' ?
if spots == 3
then Nothing
else Just (score + spots))

continue :: Score -> Bool
continue scoreInt =
let score = fromIntegral scoreInt :: Rational
in  Dist.expected
(Dist.uniform (0 : map (score+) [1,2,4,5,6])) > score

-- | optimal strategy
strategy :: Fractional prob => Trans.T prob (Maybe Score)
strategy s0 =
maybe
(return Nothing)
(\score ->
if continue score
then roll s0
else return s0) s0

-- | distribution of the scores that are achieved with the optimal strategy
game :: Fractional prob => Dist.T prob (Maybe Score)
game =
Trans.compose (replicate 18 strategy) (Just 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 (Maybe Score))
walk n =
Rnd.run \$