[英]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)
为h
, f
是addStuff
的最后2行。 当(+10)
为h
, f
是addStuff
的最后一行(在本例中为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.