[英]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)
为h
, f
是addStuff
的最后2行。 When (+10)
is h
, f
is the last line (in this case the return statement) of addStuff
. 当
(+10)
为h
, f
是addStuff
的最后一行(在本例中为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.