为什么要在 monad 中使用这种特殊的函数类型? [英] Why use such a peculiar function type in monads?

查看:24
本文介绍了为什么要在 monad 中使用这种特殊的函数类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

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