Reputation: 629
I am having trouble understanding the return in the execution of flipThree in the following implementation:
import Data.Ratio
import Data.List
newtype Prob a = Prob { getProb :: [(a,Rational)] } deriving Show
-- Functor
instance Functor Prob where
fmap f (Prob xs) = Prob $ map (\(x,p) -> (f x,p)) xs
-- Applicative
instance Applicative Prob where
pure x = Prob [(x,1%1)]
Prob [(x,r)] <*> something = fmap x something
-- Flatten works as join for Monads
flatten :: Prob (Prob a) -> Prob a
flatten (Prob xs) = Prob $ concat $ map multAll xs
where multAll (Prob innerxs,p) = map (\(x,r) -> (x,p*r)) innerxs
-- Monad
instance Monad Prob where
return x = Prob [(x,1%1)]
m >>= f = flatten (fmap f m)
fail _ = Prob []
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)]
flipThree :: Prob Bool
flipThree = do
a <- coin
b <- coin
c <- loadedCoin
return (all (==Tails) [a,b,c])
I can follow along the implementation of flipThree until I get to the following line:
return (all (==Tails) [a,b,c])
According to the result that I get, that is the following:
Prob {getProb = [(False,1 % 40),(False,9 % 40),(False,1 % 40),(False,9 % 40),(False,1 % 40),(False,9 % 40),(False,1 % 40),(True,9 % 40)]}
I can see that it comes from having this before :
Prob {getProb = [([Heads,Heads,Heads],1 % 40),([Heads,Heads,Tails],9 % 40),([Heads,Tails,Heads],1 % 40),([Heads,Tails,Tails],9 % 40),([Tails,Heads,Heads],1 % 40),([Tails,Heads,Tails],9 % 40),([Tails,Tails,Heads],1 % 40),([Tails,Tails,Tails],9 % 40)]}
As long as I can see there is a little bit of the non-determinism of the list monad but i don't get to see why. My problem is understanding why all the possible outcomes of the Coin are being concatenated in the first parameter of the tuples as they are when we get this for example:
[([Heads,Heads,Heads],1 % 40),([Heads,Heads,Tails],9 % 40)]
Why is the monad list doing that when the Monad Prob is defined in a different way and in the return is supposed to return a Prob with the Rational 1 % 1 ?
Note:
The link to the tutorial is here:
http://learnyouahaskell.com/for-a-few-monads-more#making-monads
I would really appreciate any help you can provide me as long as I've been stucked understanding all this the whole week.
Thanks in advance.
Upvotes: 2
Views: 122
Reputation: 52049
The Prob monad works just like the List monad except that it also keeps track of the current probability of all of the selections. When you finally return
something, this current probability is multiplied by 1%1 to give the probability in the tuple.
We need the 1%1 at then end because the probability is set up as product of terms, and the final term in this product is 1%1.
Here is walkthrough of what happens with this monadic expression:
do a <- coin
b <- coin
return (a == b)
Upvotes: 1