我刚开始学习 Haskell,正在尝试理解 Monad。 Monad 绑定运算符 -- >>=
-- 有一个非常奇怪的类型签名:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
为了简化,我们将m
替换为Maybe
:(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
请注意,这个定义可能以三种不同的方式书写:
(>>=) :: Maybe a -> (Maybe a -> Maybe b) -> Maybe b
(>>=) :: Maybe a -> ( a -> Maybe b) -> Maybe b
(>>=) :: Maybe a -> ( a -> b) -> Maybe b
这三个中间的那个最不对称。然而,如果我们想要避免(LYAH所谓的样板代码),我理解第一个有点无意义。然而,在接下来的两个中,我更喜欢最后一个。对于Maybe
,它应该如下所示:
当定义为:
(>>=) :: Maybe a -> (a -> b) -> Maybe b
instance Monad Maybe where
Nothing >>= f = Nothing
(Just x) >>= f = return $ f x
在这里,a -> b
是一个普通函数。此外,我没有立即看到任何不安全的地方,因为 Nothing
在函数应用之前捕获了异常,所以除非得到 Just a
,否则不会调用 a -> b
函数。那么也许有一些对我不明显的东西导致了 (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
定义优先于更简单的 (>>=) :: Maybe a -> (a -> b) -> Maybe b
定义?是否存在某些固有问题与(我认为是)更简单的定义相关联?
f :: Maybe a -> (Maybe a -> Maybe b) -> Maybe b == flip ($); and
g :: Maybe a -> ( a -> b) -> Maybe b == flip fmap。因此,你列出的其他函数都是有用的且存在的,它们只是存在于
Monad`之外的另一个位置。 - user2407038Maybe a -> (a -> b) -> Maybe b
不能绑定返回Maybe b
的函数。在计算过程中,你将无法得到Nothing
。 - user253751Maybe a -> Maybe (a -> b) -> Maybe b
,这基本上是来自Applicative
的<*>
(介于 Functor 和 Monad 之间)。 - Matt Fenwick