[英]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.