ยง Discrete random distributions with conditioning in 20 lines of haskell
newtype D a = D { unD :: [(a, Double)] } deriving(Eq, Show, Ord)
instance Functor D where
fmap f (D xs) = D $ fmap (\(a, d) -> (f a, d)) xs
instance Monad D where
return x = D $ [(x, 1.0)]
(D as) >>= f = D $ do
(a, p) <- as
(b, p2) <- unD (f a)
return $ (b, p * p2)
instance Applicative D where
pure = return
ff <*> fa = do
f <- ff
a <- fa
return $ f a
condition :: Bool -> D ()
condition True = D [((), 1.0)]
condition False = D [((), 0.0)]
dice :: D Int
dice = let p = 1.0 / 6 in D $ [(x, p) | x <- [1..6]]
dice_hard :: D Int
dice_hard = do
x <- dice
condition $ x > 3
return $ x
main :: IO ()
main = do
print dice
print dice_hard
This gives the output:
D {unD = [(1,0.16666666666666666),
(2,0.16666666666666666),
(3,0.16666666666666666),
(4,0.16666666666666666),
(5,0.16666666666666666),
(6,0.16666666666666666)]}
D {unD = [(1,0.0),
(2,0.0),
(3,0.0),
(4,0.16666666666666666),
(5,0.16666666666666666),
(6,0.16666666666666666)]}
Notice that D a ~= WriterT (Product Float) []
!