为什么在单子中使用这种特殊的功能类型? [英] Why use such a peculiar function type in monads?

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

问题描述

Haskell是新手,我正试图弄清楚这个Monad的事情。一元绑定运算符 - >> = - 具有非常特殊的类型签名:

 (>> =):: Monad m => m a  - > (a  - > m b) - > mb 

为简化起见,我们用 Maybe 替代 m

 (>> =):: Maybe a - > (a  - >可能b) - >也许b 

但是,请注意,定义可以写成三不同的方式:

 (>> =):: Maybe a  - > (也许a  - >也许b) - >也许b 
(>> =)::也许a - > (a - >可能b) - >也许b
(>> =)::也许a - > (a - > b) - >也许b

三者中的一个是最不对称的。然而,据我所知,如果我们想避免(LYAH称为<样板代码),那么第一个是没有意义的。但是,在接下来的两个,我宁愿最后一个。对于也许,这看起来像:



当它定义为:

 (>> =):: Maybe a  - > (a  - > b) - >也许b 

实例Monad也许其中
Nothing>> = f = Nothing
(Just x)>> = f = return $ fx

这里, a - > b 是一个普通的函数。另外,我不会立即看到任何不安全的东西,因为 Nothing 会在函数应用程序之前捕获异常,所以 a - >除非获得 Just a ,否则不会调用b 函数。

所以也许有些东西对我来说并不明显,这导致了(>> =):: Maybe a - > ; (a - >可能b) - >也许b 定义优于简单得多的(>> =):Maybe a - > (a - > b) - >也许b 定义?是否存在一些与(我认为是)更简单的定义相关的固有问题?解析方案

如果您认为它更对称在下面的派生函数中(从 Control.Monad ):

  (> =>):: Monad m => (a  - > m b) - > (b→m c)→> (a  - > mc)
(f> => g)x = fx>> = g

这个函数的意义重大的原因是它服从三个有用的方程:

pre $ - 相关性
(f> => g)> => h = f> => (g> => h)

- 左身份
返回> => f = f

- 正确的身份
f> =>返回= f

这些是类别法,如果您将它们翻译为使用(>> =)>而不是(> =>),你会得到三条monad规则:

 < code>>> = h = m>> = \ x  - > (gx>> = h)

return x>> = f = fx

m>> = return = m

所以它的确不是(>> =)而是(> =>)是您正在寻找的对称运算符。然而,我们通常认为(>> =)的原因是因为这就是 do 表示法desugars。


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

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

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:

When this is defined as:

(>>=) :: Maybe a -> (a -> b) -> Maybe b

instance Monad Maybe where
   Nothing  >>= f = Nothing
   (Just x) >>= f = return $ f x

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.

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?

解决方案

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

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

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.

这篇关于为什么在单子中使用这种特殊的功能类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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