Learn You a Haskell presents the Prob
newtype:
newtype Prob a = Prob { getProb :: [(a,Rational)] } deriving Show
Here's Prob
's definitions:
instance Functor Prob where
fmap f (Prob xs) = Prob $ map (\(x,p) -> (f x,p)) xs
instance Monad Prob where
return x = Prob [(x, 1%1)]
p >>= f = flatten (fmap f p)
And then the supporting functions:
flatten :: Prob (Prob a) -> Prob a
flatten = Prob . convert . getProb
convert :: [(Prob a, Rational)] -> [(a, Rational)]
convert = concat . (map f)
f :: (Prob a, Rational) -> [(a, Rational)]
f (p, r) = map (mult r) (getProb p)
mult :: Rational -> (a, Rational) -> (a, Rational)
mult r (x, y) = (x, r*y)
I wrote the flatten, convert, f, and mult functions, so I'm comfortable with them.
Then we apply >>=
to the following example, involving a data type, Coin
:
data Coin = Heads | Tails deriving (Show, Eq)
coin :: Prob Coin
coin = Prob [(Heads, 1%2), (Tails, 1%2)]
loadedCoin :: Prob Coin
loadedCoin = Prob [(Heads, 1%10), (Tails, 9%10)]
LYAH says, If we throw all the coins at once, what are the odds of all of them landing tails?
flipTwo:: Prob Bool
flipTwo= do
a <- coin -- a has type `Coin`
b <- loadedCoin -- similarly
return (all (== Tails) [a,b])
Calling flipTwo
returns:
Prob {getProb = [(False,1 % 20),(False,9 % 20),(False,1 % 20),(True,9 % 20)]}
flipTwo
can be re-written with >>=
:
flipTwoBind' :: Prob Bool
flipTwoBind' = coin >>=
\x -> loadedCoin >>=
\y -> return (all (== Tails) [x,y])
I'm not understanding the type of return (all (== Tails) [x,y])
. Since it's the right-hand side of >>=
, then its type must be a -> m b
(where Monad m
).
My understanding is that (all (==Tails) [x,y])
returns True or False
, but how does return
lead to the above result:
Prob {getProb = [(False,1 % 20),(False,9 % 20),(False,1 % 20),(True,9 % 20)]}
?