繁体   English   中英

在learnyouahaskell 教程中,这个“Prob”monad 的返回是如何工作的?

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

我在以下实现中无法理解执行 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 Prob 以不同的方式定义并且返回应该返回一个带有 Rational 1 % 1 的 Prob 时,为什么 monad 列表会这样做?

笔记:

教程链接在这里:

http://learnyouahaskell.com/for-a-few-monads-more#making-monads

我真的很感激你能提供的任何帮助,只要我整个星期都在理解这一切。

提前致谢。

Prob monad 的工作方式与 List monad 类似,除了它还跟踪所有选择的当前概率。 当你最终return一些东西时,这个当前概率乘以 1%1 来给出元组中的概率。

我们需要最后的 1%1,因为概率被设置为项的乘积,而这个乘积中的最后一项是 1%1。

下面是这个 monadic 表达式发生了什么的演练:

do a <- coin
   b <- coin
   return (a == b)
  1. a - ( v1 , p1 ) 选择一个值和概率。 这将a设置为v1以及当前概率公式p1 * ... 的公式。 我们不会知道......是什么,直到到达 monadic 表达式末尾的 return 为止。
  2. b - ( v2 , p2 ) 选择一个值和概率。 这将b设置为v2并且当前概率公式扩展为p1 * p2 * ...
  3. 计算布尔值a == b ,并通过将 ... 替换为 1%1 来完成当前的概率计算。 生成的 Prob 元组将是 (v1 == v2, p1 * p2 * 1)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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