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

Gui*_*ume 2 haskell bind composition

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

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

那么区别是什么呢 ?

Yur*_*nko 6

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

(.) :: (b -> c) -> (a -> b) -> (a -> c)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

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

f = g . h
Run Code Online (Sandbox Code Playgroud)

相当于

f x = g (h x)
Run Code Online (Sandbox Code Playgroud)

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

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

因此,让它x在上下文中有价值。我们的上下文是可为空(Maybemonad),值是2。因此,x = Just 2。例如,我们可以通过从某个关联容器中进行查找来获取它(这种操作可能会失败,这就是为什么这样做的原因Maybe Int,而不是Int)。

现在,我们希望将其传递x给一些f接受公正Int并可能失败的算术函数,因此其签名如下:

f :: Int -> Maybe Int
Run Code Online (Sandbox Code Playgroud)

由于类型不匹配,我们不能仅仅传递我们的值。我们可以使用来打开包装x并处理某些情况if,但是我们可以使用几乎所有其他语言来进行处理。在haskell中,我们可以使用(>>=)

x >>= f
Run Code Online (Sandbox Code Playgroud)

这允许链接效果:

  • 如果xNothing,则结果Nothing立即
  • 否则x打开包装并传递给f

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

x = a?.func1()?.func2();
Run Code Online (Sandbox Code Playgroud)

它会null在每个“步骤”中进行检查,如果成功则null返回或立即返回该值。在haskell中,它看起来像:

x = a >>= func1 >>= func2
Run Code Online (Sandbox Code Playgroud)

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


che*_*ner 5

(>>=)是一种功能应用形式。

(>>=)          :: Monad m => m a -> (a -> m b) -> m b
flip ($)       ::              a -> (a ->   b) ->   b
Run Code Online (Sandbox Code Playgroud)

它接受一个值,但“提取”其中的一部分以应用给定的函数。链接两个功能,如x >>= f >>= g需要的参数类型g不同的选自(但在同一类型相似于)的返回类型f,不同于组合物,这就要求类型来匹配准确

与组成return,这真的刚刚的功能应用,但仅限于某些类型的功能。

flip ($)       ::              a -> (a ->   b) ->   b
(>>=) . return :: Monad m =>   a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

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

(.)   ::            (b ->   c) -> (a ->   b) -> a ->   c
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
Run Code Online (Sandbox Code Playgroud)

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