繁体   English   中英

Haskell中的函数monad中的绑定是如何工作的?

[英]How binding works in function monads in Haskell?

从了解到一个哈克尔: http//learnyouahaskell.com/for-a-few-monads-more

函数的Monad实例是这样的:

instance Monad ((->) r) where  
    return x = \_ -> x  
    h >>= f = \w -> f (h w) w 

我无法理解以下内容的输出:

import Control.Monad.Instances  

addStuff :: Int -> Int  
addStuff = do  
    a <- (*2)  
    b <- (+10)  
    return (a+b)

addStuff 3返回19.书中说3作为参数传递给(*2) and (+10) 怎么样?

h >>= f = \\w -> f (hw) w ,似乎(hw)被绑定到a或b。 那么,为什么6不被传递(+10)?

我对f理解是,当(*2)hfaddStuff的最后2行。 (+10)hfaddStuff的最后一行(在本例中为return语句)。

让我们先看看do块[Haskell'10报告]

addStuff = do
    a <- (*2)
    b <- (+10)
    return (a+b)

相当于:

addStuff = (*2) >>= \a -> ((+10) >>= \b -> return (a + b))

因此可以转换内部绑定表达式( (+10) >>= \\b -> return (a + b) ),绑定定义为:

\w -> (\b -> return (a + b)) ((+10) w) w

如果我们用const替换return ,我们就得到:

\w -> (const . (a+)) ((+10) w) w

因此,我们有一个函数,它接受输入w ,然后调用const . (a+) const . (a+) on (w+10)w ,所以它将忽略最后一个w 在语义上它相当于:

(a+) . (+10)

所以现在我们的addStuf相当于:

addStuff = (*2) >>= \a -> ((a+) . (+10))

如果我们现在再次使用绑定运算符的定义,我们会看到:

\w -> (\a -> ((a+) . (+10))) ((*2) w) w

或更短:

\w -> (\a -> ((a+) . (+10))) (w*2) w

我们现在可以用(w*2)代替a并获得:

\w -> ((w*2)+) . (+10)) w

所以我们的addStuf相当于:

addStuff w = (w*2) + (w+10)

或者更简单:

addStuff w =  3*w + 10

哈斯克尔do记号是一系列的语法糖>>=绑定; 在这种情况下,对于这样的事情:

addStuff = (*2) >>= (\a -> (+10) >>= (\b -> return (a + b)))

在计算步骤之间传递更新的参数(因此将服务于一个国家的角色)是另一个monad的工作,即State monad。

函数Read monad比这更简单,工作量更少:

-- (return x) w = x
-- (h >>= f)  w = f (h w) w 

(h >>= (\a ->   g >>= (\b ->   return (f a b))))   w                   
=   
       (\a ->   g >>= (\b ->   return (f a b)))  (h w)   w
= 
(g >>= (\b ->   return (f  (h w)  b)))   w
= 
       (\b ->   return (f  (h w)  b)))  (g w)   w
= 
                return (f  (h w)  (g w))        w
= 
                        f  (h w)  (g w)  

因此,输入参数w 不变地传递到(通过扩展,全部)计算步骤。 或者在您询问的特定情况下,

    liftM2 (+) ( *2) ( +10)  w 
 = 
           (+) (w*2) (w+10) 

liftM2功能相当于你显示的do块,

liftM2 f h g =
   do {
     a <- h ;
     b <- g ;
     return (f a b) }
 =
   h >>= (\ a ->
    g >>= (\ b ->  return (f a b) ))

在任何monad。

暂无
暂无

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

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