非单子函数的Bind运算符表达式(>>=) id (+) 3求值为6的原理是什么
表达式
(>>=) id (+) 3的求值逻辑解释 这个表达式的核心是用到了Haskell中函数类型(->) r的Monad实例(也就是常说的Reader Monad的基础实现),推导过程如下:
1. 先明确函数Monad的(>>=)定义
标准Monad中(>>=)的类型签名为:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
当m取(->) r(即输入类型为r的单参数函数)时,替换后(>>=)的实际类型为:
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
对应的底层实现固定为:
f >>= g = \r -> g (f r) r
这个实现的作用是把公共输入参数
r隐式传递给所有依赖该参数的函数,不用手动重复传参。
2. 代入表达式逐次化简
我们的表达式(>>=) id (+) 3可以拆分推导:
- 第一步:将
f = id、g = (+)代入(>>=)的实现:(>>=) id (+) = \r -> (+) (id r) r - 第二步:
id r的返回值就是r,所以可以简化为:(>>=) id (+) = \r -> (+) r r - 第三步:传入最后的参数
3调用上述lambda函数:(\r -> (+) r r) 3 = (+) 3 3 = 6
3. 参数3被应用两次的原因
函数Monad的(>>=)实现逻辑本身就会把最后传入的参数r(这里就是3)用两次:第一次传给第一个函数f拿到返回值,第二次作为第二个函数g的第二个入参。
这里因为第一个函数f是id,所以f r的结果就是r本身,最终(+)的两个入参都是r也就是3,所以会出现参数被用两次的效果。
内容的提问来源于stack exchange,提问作者pharmaz0ne
相关产品推荐
相关产品推荐

