首页 > 解决方案 > bind和join是什么关系?

问题描述

我得到的印象是(>>=)(由 Haskell 使用)和join(由数学家首选)是“相等的”,因为可以根据另一个来写一个:

import Control.Monad (join)

join x = x >>= id
x >>= f = join (fmap f x)

此外,每个 monad 都是一个仿函数,因为bind可以用来替换fmap

fmap f x = x >>= (return . f)

我有以下问题:

  1. 是否有(非递归的)fmap定义join?(fmap f x = join $ fmap (return . f) x遵循上面的等式,但是是递归的。)

  2. “每个单子都是函子”是使用时的结论bind(在单子的定义中),但使用时的假设join

  3. bind比 更“强大”吗join?“更强大”是什么意思?

标签: haskellmonadscategory-theory

解决方案


monad 可以定义为

  • return :: a -> m a
  • bind :: m a -> (a -> m b) -> m b

或者在以下方面:

  • return :: a -> m a
  • fmap :: (a -> b) -> m a -> m b
  • join :: m (m a) -> m a

对于您的问题:

  1. 不,我们不能根据 来定义fmapjoin否则我们可以fmap从上面的第二个列表中删除。
  2. 不,“每个 monad 都是函子”是关于一般 monad 的陈述,无论您是用andbind还是用 来定义特定的 monad 。如果您看到第二个定义,则更容易理解该语句,但仅此而已。joinfmap
  3. 是的,bindjoin. join如果您的意思是“强大”,它具有定义 monad 的能力(总是与fmap结合),它与“强大”完全一样return

对于直觉,请参见例如此答案-bind允许您将策略/计划/计算(在上下文中)组合或链接在一起。例如,让我们使用Maybe上下文(或Maybemonad):

λ: let plusOne x = Just (x + 1)
λ: Just 3 >>= plusOne
Just 4

fmap还可以让您将上下文中的计算链接在一起,但代价是每一步都会增加嵌套。 [1]

λ: fmap plusOne (Just 3)
Just (Just 4)

这就是为什么您需要join:将两层嵌套压缩为一层。记住:

join :: m (m a) -> m a

只有挤压步骤不会让你走得很远。您还fmap需要有一个 monad – and return,这Just在上面的示例中。

[1]:不要以相同的顺序接受他们的两个论点fmap(>>=)但不要让你感到困惑。


推荐阅读