Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 理解“newtype Prob”的“bind”`_Haskell - Fatal编程技术网

Haskell 理解“newtype Prob”的“bind”`

Haskell 理解“newtype Prob”的“bind”`,haskell,Haskell,显示Probnewtype: newtype Prob a=Prob{getProb::[(a,Rational)]}派生Show 以下是Prob的定义: instance Functor Prob where fmap f (Prob xs) = Prob $ map (\(x,p) -> (f x,p)) xs instance Monad Prob where return x = Prob [(x, 1%1)] p >>= f = f

显示
Prob
newtype:

newtype Prob a=Prob{getProb::[(a,Rational)]}派生Show

以下是
Prob
的定义:

instance Functor Prob where  
    fmap f (Prob xs) = Prob $ map (\(x,p) -> (f x,p)) xs  

instance Monad Prob where
    return x = Prob [(x, 1%1)]
    p >>= f  = flatten (fmap f p)  
然后是支持功能:

flatten :: Prob (Prob a) -> Prob a
flatten = Prob . convert . getProb 

convert :: [(Prob a, Rational)] -> [(a, Rational)]
convert = concat . (map f)

f :: (Prob a, Rational) -> [(a, Rational)]
f (p, r) = map (mult r) (getProb p)

mult :: Rational -> (a, Rational) -> (a, Rational)
mult r (x, y) = (x, r*y)
我编写了展平、转换、f和mult函数,所以我对它们很熟悉

然后,我们将
>=
应用于以下示例,其中涉及一个数据类型,
Coin

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)]
LYAH说,
如果我们一次扔掉所有硬币,它们落在尾巴上的几率是多少?

flipTwo:: Prob Bool
flipTwo= do
  a <- coin       -- a has type `Coin`
  b <- loadedCoin -- similarly
  return (all (== Tails) [a,b])
flipTwo
可以使用
>=
重新写入:

flipTwoBind' :: Prob Bool
flipTwoBind' = coin >>= 
                    \x -> loadedCoin   >>= 
                                       \y -> return (all (== Tails) [x,y])
我不理解返回的类型(全部(=尾部)[x,y])。因为它是
>=
的右侧,所以它的类型必须是
a->mb
(其中
Monad m

我的理解是
(all(=Tails)[x,y])
返回
True或False
,但是
返回如何导致上述结果:


Prob{getProb=[(False,1%20),(False,9%20),(False,1%20),(True,9%20)]

请注意,
=
运算符的RHS是一个lambda表达式,而不是
return
的应用程序:

\y -> return (all (== Tails) [x,y])
此lambda具有预期的类型
(Monad m)=>a->mb

让我们从底部构建类型:

正如您所说,
all(=Tails)[x,y]
返回
True
False
。换句话说,它的类型是
Bool

现在,在ghci中检查
return
的类型,我们看到:

Prelude> :t return
return :: Monad m => a -> m a
所以
return(all(=Tails)[x,y])
是类型
Monad m=>m Boolean

将其包装在lambda中,然后给出类型
(Monad m)=>a->m Boolean

(注意,在此过程中,编译器将推断出具体的monad类型是
Prob

您应该将
return
看作是取一个常规值并将其包装成一个
Monad

添加:

让我们分析一下

flipTwoBind' = coin >>= 
                \x -> loadedCoin   >>= 
                                   \y -> return (all (== Tails) [x,y])
我们首先注意到,这里最外层的表达式是
(>>=)
的一个应用程序,其类型为:

Prelude> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
LHS是
coin
,其类型为
Prob coin
,因此我们立即推断
m
Prob
a
coin
。这意味着对于某些类型的
b
,RHS必须具有类型
Coin->Prob b
。现在让我们看看RHS:

\x -> loadedCoin >>= \y -> return (all (== Tails) [x,y])
这里我们有一个lambda,它返回
(>>=)
应用程序的结果,因此lambda具有类型

(Monad m) => a -> m b
这与应用第一个
(>>=)
的预期类型相匹配,因此
a
这里是
Coin
m
Prob

现在分析
(>>=)
的内部应用程序,我们看到它的类型被推断为

(>>=) :: Prob Coin -> (Prob -> Prob b) -> Prob b
我们已经分析了第二个
(>>=)
,因此
b
被推断为
Bool

(请注意,这可能不是编译器用来推断类型的确切顺序。它恰好是我分析此答案的类型时所遵循的顺序。)

(我将称您的
硬币
fairCoin
)您有:

flipTwoBind' :: Prob Bool
flipTwoBind' = fairCoin     >>=  g   where
   g x       = loadedCoin   >>=  h   where
     h y     = return z              where 
       z     = all (== Tails) [x,y]
根据
(>>=)
的类型,我们得到:

fairCoin ::         Prob Coin
(>>=) :: Monad m => m    a    ->  (a -> m b) -> m b       | m ~ Prob, a ~ Coin
                    fairCoin  >>=    g       :: m b       | g :: Coin -> Prob b
flipTwoBind'                              :: Prob Bool    | m ~ Prob, b ~ Bool
因此,
g::Coin->Prob Bool
gx::Prob Bool
提供了
x::Coin

由于
gx=loadedCoin>=h
,我们有

loadedCoin ::       Prob Coin
(>>=) :: Monad m => m    a    ->  (a -> m b) -> m    b 
                  loadedCoin  >>=    h       :: Prob Bool
所以,
h::Coin->Prob Bool
z::Bool
返回z::Prob Bool

all ::  (a -> Bool) -> [a] -> Bool
all        p           []  :: Bool

return :: (Monad m) => a -> m a
z      ::           Bool
return                 z :: m Bool           | m ~ Prob so return z :: Prob Bool
由于
Prob a
本质上是一个标记的
a
结果对及其相应概率的关联列表,
Prob Bool
是一个
Bool
结果对及其概率的列表


翻译为特定的
Prob
一元代码,内联所有函数,
flipTwoBind'
成为

flipTwoBind' = fairCoin     >>=  g
   = flatten (fmap g fairCoin)
   = Prob . convert . getProb $ 
             Prob $ map (\(x,p) -> (g x,p)) $ getProb fairCoin
   = Prob . concat . map (\(x,p) -> map (\(x, y) -> (x, p*y)) $ getProb x)
                  . map (\(x,p) -> (g x,p)) $ getProb fairCoin
(请参见内部的
Prob
getProb
相互抵消的效果…)

切换到基于普通列表的代码(使用
gL xs=getProb(g(Prob xs))
fairCoinL=getProb fairCoin
等),相当于

   = concat . map (\(x,p) -> map (second (p*)) x)
            . map (\(x,p) -> (gL x,p)) $ fairCoinL
   = concat . map (\(x,p) -> map (second (p*)) $ gL x) $ fairCoinL
   = [(v,p*q) | (x,p) <- fairCoinL, (v,q) <- gL x]
   = ....
   = [(z,r)   | (x,p) <- [(Heads,   1%2),  (Tails,   1%2 )],   -- do a <- fairCoin
                (y,q) <- [(Heads, p*1%10), (Tails, p*9%10)],   --    b <- loadedCoin
                (z,r) <- [(all (== Tails) [x,y],   q*1%1 )] ]  --    return ... all ...
   = [(False,1 % 20),(False,9 % 20),(False,1 % 20),(True,9 % 20)]
=concat。地图(\(x,p)->地图(第二(p*)x)
. 地图(\(x,p)->(gL x,p))$fairCoinL
=concat。地图(\(x,p)->地图(第二(p*)$gL x)$fairCoinL

=[(v,p*q)|(x,p)谢谢,代码学徒。关于你能说得更多吗请注意,在这个过程中,编译器会推断出具体的monad类型是Prob?我相信Prob的定义,即flatte(fmap fp)
>=
正在发挥作用,但我不清楚。@KevinMeredith我不完全确定这些细节。我猜你必须分析
flipTwoBind'
的完整定义的类型。最有可能的是从
硬币
loadedCoin
的类型中进行推断第二,我增加了对类型推断的更详细分析
   = concat . map (\(x,p) -> map (second (p*)) x)
            . map (\(x,p) -> (gL x,p)) $ fairCoinL
   = concat . map (\(x,p) -> map (second (p*)) $ gL x) $ fairCoinL
   = [(v,p*q) | (x,p) <- fairCoinL, (v,q) <- gL x]
   = ....
   = [(z,r)   | (x,p) <- [(Heads,   1%2),  (Tails,   1%2 )],   -- do a <- fairCoin
                (y,q) <- [(Heads, p*1%10), (Tails, p*9%10)],   --    b <- loadedCoin
                (z,r) <- [(all (== Tails) [x,y],   q*1%1 )] ]  --    return ... all ...
   = [(False,1 % 20),(False,9 % 20),(False,1 % 20),(True,9 % 20)]
   = [(all (== Tails) [x,y], q)                                -- ... all ... <$>
              | (x,p) <- [(Heads,   1%2),  (Tails,   1%2 )],   --   fairCoin <*>
                (y,q) <- [(Heads, p*1%10), (Tails, p*9%10)] ]  --   loadedCoin