简体   繁体   English

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

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

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

Monad instance for function is this: 函数的Monad实例是这样的:

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

I am having trouble understanding the output of the following: 我无法理解以下内容的输出:

import Control.Monad.Instances  

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

addStuff 3 returns 19. Book says 3 gets passed as parameters to both (*2) and (+10) . addStuff 3返回19.书中说3作为参数传递给(*2) and (+10) How? 怎么样?

From h >>= f = \\w -> f (hw) w , it seems like (hw) is getting bound to a or b. h >>= f = \\w -> f (hw) w ,似乎(hw)被绑定到a或b。 So, why 6 is not being passed in (+10)? 那么,为什么6不被传递(+10)?

My understanding of f here is that when (*2) is h , f is the last 2 lines of addStuff . 我对f理解是,当(*2)hfaddStuff的最后2行。 When (+10) is h , f is the last line (in this case the return statement) of addStuff . (+10)hfaddStuff的最后一行(在本例中为return语句)。

Let us first desugar the do block [Haskell'10 report] : 让我们先看看do块[Haskell'10报告]

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

is equivalent to: 相当于:

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

The inner bind expression ( (+10) >>= \\b -> return (a + b) ), can thus be converted, with the bind definition to: 因此可以转换内部绑定表达式( (+10) >>= \\b -> return (a + b) ),绑定定义为:

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

and if we substitute return with const , we thus obtain: 如果我们用const替换return ,我们就得到:

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

We thus have a function that takes as input w , and then calls const . (a+) 因此,我们有一个函数,它接受输入w ,然后调用const . (a+) const . (a+) on (w+10) and w , so it will ignore the last w . const . (a+) on (w+10)w ,所以它将忽略最后一个w Semantically it is equivalent to: 在语义上它相当于:

(a+) . (+10)

So now our addStuf is equivalent to: 所以现在我们的addStuf相当于:

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

and if we now use the definition for the bind operator again, we see: 如果我们现在再次使用绑定运算符的定义,我们会看到:

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

or shorter: 或更短:

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

We can now substitue a with (w*2) and obtain: 我们现在可以用(w*2)代替a并获得:

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

So our addStuf is equivalent to: 所以我们的addStuf相当于:

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

or more simple: 或者更简单:

addStuff w =  3*w + 10

Haskell do notation is syntactic sugar for a series of >>= bindings; 哈斯克尔do记号是一系列的语法糖>>=绑定; in this case, for something like this: 在这种情况下,对于这样的事情:

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

Passing the updated argument between the computation steps (which would thus be serving a role of a state) is the job of another monad, namely the State monad. 在计算步骤之间传递更新的参数(因此将服务于一个国家的角色)是另一个monad的工作,即State monad。

The function aka Reader monad is simpler than that, does less work: 函数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)  

Thus the input argument w is passed unchanged into both (by extension, all) the computation steps. 因此,输入参数w 不变地传递到(通过扩展,全部)计算步骤。 Or in the specific case you ask about, 或者在您询问的特定情况下,

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

liftM2 function is equivalent to the do block that you show, liftM2功能相当于你显示的do块,

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

in any monad. 在任何monad。

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

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