madd a b = do aa <- a
bb <- b
return (aa + bb)
data Counter a = Counter a Int
deriving (Show,Eq)
instance Functor Counter where
fmap f (Counter a i) = Counter (f a) i
instance Applicative Counter where
pure x = Counter x 0
Counter f i <*> Counter x j = Counter (f x) (i + j)
instance Monad Counter where
return x = Counter x 0
Counter a i >>= f =
let Counter b j = f a
in Counter b (i + j + 1)
So suppose for this code one runs:
madd (Counter 10 43) (Counter 32 1)
and one gets Counter 42 46
.
I do not get how this produces this result. So madd
"calls" monad Counter
, then passes +
function to >>=
part of the monad instance. But then I find how the monad instance calls/passes functions/results very puzzling.
Can anyone explain in detail how intermediate calculations work?
答案 0 :(得分:1)
tl; dr :拥抱do
,避开 bind !无论如何,这是一个实施细节。 do
可以真正被视为一种公理化的主要符号,因为&#34; monads&#34; 首先说出"programs"是一种奇特的方式(< em>在这里插入对冲限定符)。
将do
表示法移植到基于 bind 的代码中,
do { v <- m ; f v } === m >>= f
相反,反方向,
Counter a i >>= f === do { v <- Counter a i ; f v }
因此,您的Monad实例绑定定义,
Counter a i >>= f = Counter b (i + j + 1) where
Counter b j = f a
可以非正式地重写为
instance Monad Counter where
return x = Counter x 0
do { v <- Counter x i
; f v } = Counter y (i + j + 1) where -- the bind transformation
Counter y j = f v
v = x
现在我们可以直接操作您的do
代码,看看发生了什么:
madd (Counter 10 43) (Counter 32 1)
= do { aa <- Counter 10 43
; bb <- Counter 32 1
; return (aa + bb)
}
= do { aa <- Counter 10 43
; do { bb <- Counter 32 1 -- by Monad Laws
; return (aa + bb)
}}
= do { aa <- Counter 10 43
; f aa } where f aa = do { bb <- Counter 32 1 -- abstraction
; return (aa + bb)
}
= Counter y (43 + j + 1) -- the bind transformation
where Counter y j = f 10
= do { bb <- Counter 32 1
; return (10 + bb)
}
= do { bb <- Counter 32 1
; (return . (10 +)) bb
}
= Counter y (1 + j + 1) -- the bind transformation
where Counter y j = (return . (10 +)) 32
= return 42
= Counter 42 0
= Counter 42 (1 + 0 + 1)
= Counter 42 2
= Counter 42 (43 + 2 + 1)
= Counter 42 46
即,madd (Counter a i) (Counter b j)
生成Counter (a+b) (i+j+2)
, 2 是 bind 转换应用程序的数量。
答案 1 :(得分:0)
当您do
madd
中的a >>= \aa -> b >>= \bb -> return (a + b)
表达式变为
Awesomium.Core.AweInvalidOperationException: 'The calling thread cannot access this object because a different thread owns it.'
所以你从第一个和第二个计数器得到43加1加上两个,每个为madd
中的每个绑定学习monad时,最好避免使用符号,并始终记住我们正在分析的monad的bind(&gt;&gt; =)的具体定义