了解简单Reader Monad的do表示法:a<-(* 2),b<-(+10),return(a + b) [英] Understanding do notation for simple Reader monad: a <- (*2), b <- (+10), return (a+b)

查看:102
本文介绍了了解简单Reader Monad的do表示法:a<-(* 2),b<-(+10),return(a + b)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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)  

我试图通过松开do符号来理解此monad,因为我认为do符号隐藏了会发生的事情.

I'm trying to understand this monad by unwiding the do notation, because I think the do notation hides what happens.

如果我理解正确,就会发生这种情况:

If I understood correctly, this is what happens:

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

现在,如果采用>>=的规则,则必须将(*2)理解为h,将(\a -> (+10) >>= (\b -> return (a+b)))理解为f.将h应用于w很容易,我们只说它是2w(我不知道2w在haskell中是否有效,但出于推理的原因,请保持这种方式.现在我们必须应用h w2w.f只需为特定的a返回(+10) >>= (\b -> return (a+b)),在我们的例子中为2w,因此f (hw)(+10) >>= (\b -> return (2w+b)).最终在将其应用于w之前发生在(+10) >>= (\b -> return (2w + b))上.

Now, if we take the rule for >>=, we must understand (*2) as h and (\a -> (+10) >>= (\b -> return (a+b))) as f. Applying h to w is easy, let's just say it is 2w (I don't know if 2w is valid in haskell but just for reasoning lets keep it this way. Now we have to apply f to h w or 2w. Well, f simply returns (+10) >>= (\b -> return (a+b)) for an specific a, which is 2w in our case, so f (hw) is (+10) >>= (\b -> return (2w+b)). We must first get what happens to (+10) >>= (\b -> return (2w + b)) before finally applying it to w.

现在,我们用规则重新标识(+10) >>= (\b -> return (2w + b)),因此h+10,而f(\b -> return (2w + b)).让我们首先执行h w.我们得到w + 10.现在我们需要将f应用于h w.我们得到(return (2w + w + 10)).

Now we reidentify (+10) >>= (\b -> return (2w + b)) with our rule, so h is +10 and f is (\b -> return (2w + b)). Let's first do h w. We get w + 10. Now we need to apply f to h w. We get (return (2w + w + 10)).

所以我们要在第一个>>=中尝试将(return (2w + w + 10))应用于w.但是我完全迷路了,不知道发生了什么.

So (return (2w + w + 10)) is what we need to apply to w in the first >>= that we were tyring to uwind. But I'm totally lost and I don't know what happened.

我在以严格的方式思考吗?这真令人困惑.有没有更好的方法来考虑它?

Am I thinking in the rigth way? This is so confusing. Is there a better way to think of it?

推荐答案

您忘记了运算符>>=不仅返回f (h w) w,而且还返回\w -> f (h w) w.也就是说,它返回一个函数,而不是数字.

You're forgetting that operator >>= doesn't return just f (h w) w, but rather \w -> f (h w) w. That is, it returns a function, not a number.

通过错误地替换它,您丢失了最外面的参数w,因此也就不足为奇了,它在最终表达式中仍然是免费的.

By substituting it incorrectly you lost the outermost parameter w, so it's no wonder it remains free in your final expression.

要正确执行此操作,您必须完全用函数主体代替它们的调用,而不能丢弃任何东西.

To do this correctly, you have to substitute function bodies for their calls completely, without dropping stuff.

如果用最外面的>>=代替,则会得到:

If you substitute the outermost >>=, you will get:

(*2) >>= (\a -> ...) 
==
\w -> (\a -> ...) (w*2) w

然后,如果替换最里面的>>=,则会得到:

Then, if you substitute the innermost >>=, you get:

\a -> (+10) >>= (\b -> return (a+b))
==
\a -> \w1 -> (\b -> return (a+b)) (w1 + 10) w1

请注意,我使用的是w1而不是w.这是为了避免以后在组合替换项时发生名称冲突,因为这两个w来自两个不同的lambda抽象,因此它们是不同的变量.

Note that I use w1 instead of w. This is to avoid name collisions later on when I combine the substitutions, because these two ws come from two different lambda abstractions, so they're different variables.

最后,用return代替:

return (a+b)
==
\_ -> a+b

现在将最后一个替换项插入上一个替换项:

Now insert this last substitution into the previous one:

\a -> (+10) >>= (\b -> return (a+b))
==
\a -> \w1 -> (\b -> return (a+b)) (w1 + 10) w1
==
\a -> \w1 -> (\b -> \_ -> a+b) (w1 + 10) w1

最后将其插入到第一个替换中:

And finally insert this into the very first substitution:

(*2) >>= (\a -> ...) 
==
\w -> (\a -> ...) (w*2) w
==
\w -> (\a -> \w1 -> (\b -> \_ -> a+b) (w1 + 10) w1) (w*2) w

现在所有的替代品都在竞争,我们可以减少.首先应用最里面的lambda \b -> ...:

And now that all substitutions are compete, we can reduce. Start with applying the innermost lambda \b -> ...:

\w -> (\a -> \w1 -> (\_ -> a+w1+10) w1) (w*2) w

现在应用新的最里面的lambda \_ -> ...:

Now apply the new innermost lambda \_ -> ...:

\w -> (\a -> \w1 -> a+w1+10) (w*2) w

现在申请\a -> ...:

\w -> (\w1 -> w*2+w1+10) w

最后应用剩下的唯一lambda \w1 -> ...:

And finally apply the only remaining lambda \w1 -> ...:

\w -> w*2+w+10

瞧!整个功能降低到\w -> (w*2) + (w+10),完全符合预期.

And voila! The whole function reduces to \w -> (w*2) + (w+10), completely as expected.

这篇关于了解简单Reader Monad的do表示法:a&lt;-(* 2),b&lt;-(+10),return(a + b)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆