{- |
Consider a family of two children.  Given that there is a boy in the family,
what is the probability that there are two boys in the family?
-}

module Numeric.Probability.Example.Boys where

import qualified Numeric.Probability.Distribution as Dist
import Numeric.Probability.Distribution ((??), (?=<<), )

import Control.Monad (liftM2, )


type Probability = Rational
type Dist a = Dist.T Probability a

data Child = Boy | Girl
             deriving (Child -> Child -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Child -> Child -> Bool
$c/= :: Child -> Child -> Bool
== :: Child -> Child -> Bool
$c== :: Child -> Child -> Bool
Eq,Eq Child
Child -> Child -> Bool
Child -> Child -> Ordering
Child -> Child -> Child
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Child -> Child -> Child
$cmin :: Child -> Child -> Child
max :: Child -> Child -> Child
$cmax :: Child -> Child -> Child
>= :: Child -> Child -> Bool
$c>= :: Child -> Child -> Bool
> :: Child -> Child -> Bool
$c> :: Child -> Child -> Bool
<= :: Child -> Child -> Bool
$c<= :: Child -> Child -> Bool
< :: Child -> Child -> Bool
$c< :: Child -> Child -> Bool
compare :: Child -> Child -> Ordering
$ccompare :: Child -> Child -> Ordering
Ord,Int -> Child -> ShowS
[Child] -> ShowS
Child -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Child] -> ShowS
$cshowList :: [Child] -> ShowS
show :: Child -> String
$cshow :: Child -> String
showsPrec :: Int -> Child -> ShowS
$cshowsPrec :: Int -> Child -> ShowS
Show)

type Family = (Child, Child)

birth :: Dist Child
birth :: Dist Child
birth = forall prob a. Fractional prob => Spread prob a
Dist.uniform [Child
Boy, Child
Girl]

family :: Dist Family
family :: Dist Family
family = forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) Dist Child
birth Dist Child
birth

allBoys :: Dist.Event Family
allBoys :: Event Family
allBoys (Child
c0, Child
c1) = (Child
c0 forall a. Eq a => a -> a -> Bool
== Child
Boy Bool -> Bool -> Bool
&& Child
c1 forall a. Eq a => a -> a -> Bool
== Child
Boy)

existsBoy :: Dist.Event Family
existsBoy :: Event Family
existsBoy (Child
c0, Child
c1) = (Child
c0 forall a. Eq a => a -> a -> Bool
== Child
Boy Bool -> Bool -> Bool
|| Child
c1 forall a. Eq a => a -> a -> Bool
== Child
Boy)

familyWithBoy :: Dist Family
familyWithBoy :: Dist Family
familyWithBoy = Event Family
existsBoy forall prob a.
Fractional prob =>
(a -> Bool) -> T prob a -> T prob a
?=<< Dist Family
family
{-
familyWithBoy =
   do f <- family
      guard (existsBoy f)
      return f
-}

twoBoys :: Probability
twoBoys :: Probability
twoBoys = Event Family
allBoys forall prob a. Num prob => Event a -> T prob a -> prob
?? Dist Family
familyWithBoy


countBoy :: Child -> Int
countBoy :: Child -> Int
countBoy Child
Boy = Int
1
countBoy Child
Girl = Int
0

countBoys :: Family -> Int
countBoys :: Family -> Int
countBoys (Child
c0,Child
c1) = Child -> Int
countBoy Child
c0 forall a. Num a => a -> a -> a
+ Child -> Int
countBoy Child
c1

numBoys :: Dist Int
numBoys :: Dist Int
numBoys = forall prob b a.
(Num prob, Ord b) =>
(a -> b) -> T prob a -> T prob b
Dist.map Family -> Int
countBoys Dist Family
familyWithBoy