Monad法则解释

从Haskell的一个温和的介绍,有以下monad法律。 任何人都可以直观地解释他们的意思吗?

return a >>= k             = k a
m >>= return               = m
xs >>= return . f          = fmap f xs
m >>= (x -> k x >>= h)    = (m >>= k) >>= h

这是我的尝试解释:

  • 我们期望返回函数包装a以便它的monadic本质是微不足道的。 当我们将它绑定到函数时,没有单调效果,它应该只传递a函数。

  • m的unwrapped输出传递给return ,它重新包装它。 monadic性质保持不变。 所以它和原来的monad一样。

  • 解包的值传递给f然后重新包装。 monadic性质保持不变。 这是我们将普通函数转换为单子函数时的预期行为。

  • 我没有这个法律的解释。 这确实表明monad必须是“几乎联想”的。


  • 你的描述看起来不错。 通常人们会谈到三条单子法,这两条法律分别是1,2和4.您的第三条法律略有不同,稍后我会谈谈。

    对于这三个monad定律,我发现使用Kleisli组合可以更直观地理解它们在重写时的含义:

    -- defined in Control.Monad
    (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
    mf >=> n = x -> mf x >>= n
    

    现在法律可以写成:

    1) return >=> mf = mf                  -- left identity
    2) mf >=> return = mf                  -- right identity
    4) (f >=> g) >=> h = f >=> (g >=> h)   -- associativity
    

    1)左身份法 - 返回一个值不会改变这个值,并且不会在monad中做任何事情。

    2)正确的身份法 - 返回一个值不会改变这个值,并且不会在monad中做任何事情。

    4)关联性 - 一元组合是联想的(我喜欢KennyTM的答案)

    两个身份法则基本上都是这样说的,但它们都是必需的,因为return应该在绑定操作符的两边都有身份行为。

    现在是第三法。 这个法则基本上说,当将函数提升到monad中时,Functor实例和Monad实例的行为方式都是相同的,并且它们都不是单向的。 如果我没有弄错,那么当一个单子服从其他三个法则并且函子实例服从函子法则时,那么这个声明将永远是真实的。

    这很大一部分来自Haskell Wiki。 Typeclassopedia也是一个很好的参考。


    与其他答案没有分歧,但它可能有助于将单子法看作实际描述两组属性。 正如约翰说的那样,你提到的第三条法则略有不同,但这里的其他条款可以如何拆分:

    绑定到monad的函数与常规函数一样。

    正如在约翰的回答中,所谓monad的Kleisli箭头是一个类型为a -> mb的函数。 把return当作id(<=<)作为(.) ,并且monad定律是这些的翻译:

  • id . f id . f等于f
  • f . id f . id等同于f
  • (f . g) . h (f . g) . h等于f . (g . h) f . (g . h)
  • 一元效应序列附加列表。

    大多数情况下,您可以将额外的一元结构看作与一元值相关的额外行为序列; 例如, Maybe是为了Nothing而“放弃”,为Just而“继续前进”。 结合两个monadic动作然后基本连接他们所持有的行为序列。

    在这个意义上, return再次是一个标识 - 空行为,类似于一个空的行为列表 - (>=>)是串联。 所以,单子法是这些的翻译:

  • [] ++ xs等同于xs
  • xs ++ []相当于xs
  • (xs ++ ys) ++ zs相当于xs ++ (ys ++ zs)

  • 这三条法律描述了一种荒谬的共同模式,不幸的是,Haskell无法完全表达一般性。 如果你有兴趣, Control.Category给出了“看起来像函数组合的东西”的概括,而Data.Monoid概括了后者没有涉及的类型参数的情况。


    do符号而言,规则4意味着我们可以添加一个额外的do块来对一系列monadic操作进行分组。

        do                          do
                                      y <- do
          x <- m                             x <- m
          y <- k x          <=>              k x
          h y                         h y
    

    这允许返回单值的函数正常工作。

    链接地址: http://www.djcxy.com/p/42949.html

    上一篇: Explanation of Monad laws

    下一篇: Haskell — Monad binding evaluation order