这是>>=
的类型:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
它需要一个函数作为第二个参数。
这是返回
的类型:
return :: Monad m => a -> m a
返回m a
这显然是类型检查:
(>>) :: Monad m => m a -> m b -> m b
x >> y = x >>= (\_ -> y)
但是为什么下面的类型检查和工作方式与上面的代码类似?
(>>) :: Monad m => m a -> m b -> m b
x >> y = x >>= return y
这里 return y
应该是 m a
类型,而不是 a -> m a
类型。那么它为什么有效呢?
最佳答案
你实际上在这里混合了两个不同的单子(monad),这就是正在发生的事情。 x >>= return y
在这种情况下统一为
(>>) :: ∀ m a b . Monad m => m a -> m b -> m b
x >> y = x >>= (return :: m b -> a -> m b) y
-- aka return :: (m b) -> (a->) (m b)
其中 return
在 Monad (a->)
中实现实例:
instance Monad (->) a where
return x = \_ -> x
...
它与Monad m
没有任何关系。实例。
至于为什么这个return
在函数 monad 中运行:return :: m b -> a -> m b
在编译器开始推理类型类实例之前从环境中推断出来。现在,输入 m b -> a -> m b
,即m b -> (a->m b)
,其形式为 mb -> amb
。签名return :: Monad μ => α -> μ α
因此使编译器匹配 μ α ~ amb ~ a->m b
。只有此时编译器才会真正选择 return
的 monad 实例。 ,它是通过观察 a -> m b
来做到这一点的确实具有 μ α
的形式,与 μ ~ (a->)
和α ~ m b
。因此,它必须是 (a->)
单子(monad)。
关于haskell - 在 Haskell 的绑定(bind)运算符中使用 return (>>=),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38293959/