简体   繁体   中英

How does it work the return in this "Prob" monad in the learnyouahaskell tutorial?

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.

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)
  1. Select a value and probability for a - ( v1 , p1 ). This sets a to v1 and the formula for the current probability formula p1 * ... . We won't know what ... is until return at the end of the monadic expression is reached.
  2. Select a value and probability for b - ( v2 , p2 ). This set b to v2 and the current probability formula is extended to p1 * p2 * ...
  3. Compute the boolean value a == b , and finish off the current probability computation by replacing ... with 1%1. The resulting Prob tuple will be (v1 == v2, p1 * p2 * 1).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM