为什么要在 monad 中使用这种特殊的函数类型? [英] Why use such a peculiar function type in monads?
问题描述
Haskell 的新手,我正在尝试弄清楚 Monad 的事情.monadic 绑定操作符——>>=
——有一个非常奇特的类型签名:
New to Haskell, and am trying to figure out this Monad thing. The monadic bind operator -- >>=
-- has a very peculiar type signature:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
为了简化,让我们用 Maybe
代替 m
:
To simplify, let's substitute Maybe
for m
:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
但是,请注意定义可以以三种不同的方式编写:
However, note that the definition could have been written in three different ways:
(>>=) :: Maybe a -> (Maybe a -> Maybe b) -> Maybe b
(>>=) :: Maybe a -> ( a -> Maybe b) -> Maybe b
(>>=) :: Maybe a -> ( a -> b) -> Maybe b
在三个中,中间的那个是最不对称的.但是,我知道如果我们想避免的话,第一个是没有意义的(LYAH 称之为样板代码).但是,在接下来的两个中,我更喜欢最后一个.对于 Maybe
,这看起来像:
Of the three the one in the centre is the most asymmetric. However, I understand that the first one is kinda meaningless if we want to avoid (what LYAH calls boilerplate code). However, of the next two, I would prefer the last one. For Maybe
, this would look like:
当它被定义为:
(>>=) :: Maybe a -> (a -> b) -> Maybe b
instance Monad Maybe where
Nothing >>= f = Nothing
(Just x) >>= f = return $ f x
这里,a ->b
是一个普通的函数.另外,我没有立即看到任何不安全的东西,因为 Nothing
在函数应用程序之前捕获异常 ,所以 a ->b
函数不会被调用,除非得到一个 Just a
.
Here, a -> b
is an ordinary function. Also, I don't immediately see anything unsafe, because Nothing
catches the exception before the function application, so the a -> b
function will not be called unless a Just a
is obtained.
所以也许有什么对我来说并不明显导致了 (>>=) :: 可能是 ->(a -> 也许 b) ->也许 b
定义比简单得多的 (>>=) :: 可能 a ->(a -> b) ->也许 b
定义?是否存在与(我认为是)更简单定义相关的一些固有问题?
So maybe there is something that isn't apparent to me which has caused the (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
definition to be preferred over the much simpler (>>=) :: Maybe a -> (a -> b) -> Maybe b
definition? Is there some inherent problem associated with the (what I think is a) simpler definition?
推荐答案
如果你考虑以下派生函数(来自 Control.Monad
),它会更加对称:
It's much more symmetric if you think in terms the following derived function (from Control.Monad
):
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
(f >=> g) x = f x >>= g
这个函数之所以重要,是因为它遵循三个有用的方程:
The reason this function is significant is that it obeys three useful equations:
-- Associativity
(f >=> g) >=> h = f >=> (g >=> h)
-- Left identity
return >=> f = f
-- Right identity
f >=> return = f
这些是分类法,如果您翻译他们使用 (>>=)
而不是 (>=>)
,你会得到三个 monad 法则:
These are category laws and if you translate them to use (>>=)
instead of (>=>)
, you get the three monad laws:
(m >>= g) >>= h = m >>= x -> (g x >>= h)
return x >>= f = f x
m >>= return = m
所以实际上不是 (>>=)
是优雅的运算符,而是 (>=>)
是您正在寻找的对称运算符.然而,我们通常从 (>>=)
的角度考虑的原因是因为这就是 do
符号脱糖的目的.
So it's really not (>>=)
that is the elegant operator but rather (>=>)
is the symmetric operator you are looking for. However, the reason we usually think in terms of (>>=)
is because that is what do
notation desugars to.
这篇关于为什么要在 monad 中使用这种特殊的函数类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!