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

How binding works in function monads in Haskell?

从学你一个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 returns 19. 书上说 3 作为参数传递给 (*2) and (+10)。怎么样?

h >>= f = \w -> f (h w) w 开始,似乎 (h w) 被绑定到 a 或 b。 那么,为什么 6 没有传入 (+10)?

我这里对f的理解是,当(*2)h时,f就是addStuff的最后2行。当 (+10)h 时,faddStuff.

的最后一行(在本例中是 return 语句)

Haskell do 符号是一系列 >>= 绑定的语法糖;在这种情况下,对于这样的事情:

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

让我们先desugar the do block [Haskell'10 report]:

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

如果我们将return替换为const,我们将得到:

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

因此我们有一个函数将 w 作为输入,然后在 (w+10)w 上调用 const . (a+),因此它将忽略最后一个 [=25] =].在语义上它等同于:

(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

在计算步骤之间传递更新的参数(这将充当状态的角色)是另一个 monad 的工作,即 State monad。

函数又名 Reader 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) ))

在任何单子中。