我无法理解在以下实现中执行flipThree的返回:
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])
我可以跟随flipThree的实现,直到我到达以下行:
return (all (==Tails) [a,b,c])
根据我得到的结果,以下是:
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)]}
我可以看到它来自之前:
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)]}
只要我能看到列表monad的一些非确定性,但我不明白为什么。我的问题是理解为什么Coin的所有可能结果都在元组的第一个参数中连接起来,就像我们得到这个例子时那样:
[([Heads,Heads,Heads],1 % 40),([Heads,Heads,Tails],9 % 40)]
为什么monad列表以不同的方式定义Monad Prob并且返回时应该返回一个带有Rational 1%1的Prob?
注意:
教程的链接在这里:
http://learnyouahaskell.com/for-a-few-monads-more#making-monads
只要我整整一周都被理解了这一切,我真的很感激你能提供给我的任何帮助。
提前致谢。
答案 0 :(得分:1)
Prob monad的工作原理与List monad类似,不同之处在于它还跟踪所有选择的当前概率。当你最终return
某事时,这个当前概率乘以1%1来给出元组中的概率。
我们需要1%1,因为概率设置为术语的乘积,本产品的最终术语是1%1。
以下是这个monadic表达式发生的演练:
do a <- coin
b <- coin
return (a == b)