函数组成和绑定之间的Haskell区别

时间:2019-11-21 17:02:23

标签: haskell bind composition

我无法理解Dot(函数组成)和bind(>> =)之间的区别。

如果我理解的话,这两种方法会将以前的功能结果用于新功能。

那有什么区别?

2 个答案:

答案 0 :(得分:6)

它们是完全不同的。让我们看看他们的签名:

(.) :: (b -> c) -> (a -> b) -> (a -> c)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b

正如您所说,函数组合只是将一个函数的结果作为参数传递给另一函数的一种方法,如下所示:

f = g . h

等同于

f x = g (h x)

您可以考虑将其视为某种“传送带”,其中,您的价值需要经过几个处理步骤。

但是(>>=)是完全不同的。它与诸如monad之类的上下文相关,这在某些上下文中具有某种价值(强烈建议您阅读上一个链接,如果您不熟悉它)。

因此,让x是上下文中的某些值。我们的上下文是可空性(Maybe monad),值是2。因此,x = Just 2。例如,我们可以通过从某个关联容器中查找得到它(这种操作可能会失败,这就是为什么它是Maybe Int而不是Int的原因。)

现在,我们想将x传递给某个仅接受f且可能会失败的算术函数Int,因此其签名看起来像:

f :: Int -> Maybe Int

由于类型不匹配,我们不能仅仅传递我们的值。我们可以解压缩x并用if处理某些情况,但是我们可以用几乎所有其他语言来做到这一点。在haskell中,我们可以使用(>>=)

x >>= f

这允许链接效果:

  • 如果xNothing,则结果立即为Nothing
  • 将其他x拆包并传递给f

这是operator ?.的概括,可以在某些语言中看到:

x = a?.func1()?.func2();

在每个“步骤”中检查null并在命中null时立即停止或在成功的情况下返回值。在haskell中,它看起来像:

x = a >>= func1 >>= func2

但是,与monad绑定是一个更强大的概念,例如,它使您可以使用像haskell这样的无可变性的语言来模拟状态计算。

答案 1 :(得分:4)

(>>=)是函数 application 的一种形式。

(>>=)          :: Monad m => m a -> (a -> m b) -> m b
flip ($)       ::              a -> (a ->   b) ->   b

它带有一个值,但是为了应用给定的功能,它“提取”了一部分。链接两个函数,例如x >>= f >>= g要求g的参数类型与返回类型 (但与 like 相同) f中的,与组合不同,组合要求类型完全匹配

return组成 确实是功能应用,但仅限于某些功能。

flip ($)       ::              a -> (a ->   b) ->   b
(>>=) . return :: Monad m =>   a -> (a -> m b) -> m b

(.)更像(<=<)(来自Control.Monad)。

(.)   ::            (b ->   c) -> (a ->   b) -> a ->   c
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c

但同样,它不是简单地将一个函数的结果传递给另一个函数,而是在执行应用程序之前首先“提取”一个值。