【发布时间】:2015-11-13 08:34:30
【问题描述】:
我无法理解在以下实现中执行 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)]}
只要我能看到列表单子有一点不确定性,但我不明白为什么。我的问题是理解为什么 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
只要我整整一周都无法理解这一切,我将非常感谢您能为我提供的任何帮助。
提前致谢。
【问题讨论】:
-
return确实返回一个概率为1%1的值,但您看到的结果是coin >>= (\ a -> coin >>= (\ b -> loadedCoin >>= (\ c -> return (all (== Tails) [a,b,c]))))的结果。return的结果首先通过几层>>=向上传递。这有帮助吗? -
不是返回最后一层 >>= 吗?
-
这是
>>=中嵌套最深的东西。它是 innermost 表达式。