【问题标题】:How to show that a monad is a functor and an applicative functor?如何证明 monad 是函子和应用函子?
【发布时间】:2012-02-24 06:37:48
【问题描述】:

Monad 在理论上被认为是函子的子集,特别是应用函子,尽管 Haskell 的类型系统中没有指出。

知道,给定一个 monad 并基于 returnbind,如何:

  • 派生fmap,
  • 派生<*> ?

【问题讨论】:

    标签: haskell monads functor applicative


    【解决方案1】:

    fmap = liftM(<*>) = ap。以下是liftMap 的源代码链接。我想你知道如何去除 do 符号的糖分。

    【讨论】:

      【解决方案2】:

      好吧,fmap 就是(a -> b) -> f a -> f b,也就是说,我们想用一个纯函数来转换一元动作的结果。用 do 表示法很容易写:

      fmap f m = do
        a <- m
        return (f a)
      

      或者,写成“原始”:

      fmap f m = m >>= \a -> return (f a)
      

      这是Control.Monad.liftM

      pure :: a -&gt; f a 当然是return(&lt;*&gt;) :: f (a -&gt; b) -&gt; f a -&gt; f b 有点棘手。我们有一个动作返回一个函数,一个动作返回它的参数,我们想要一个动作返回它的结果。再次使用 do 表示法:

      mf <*> mx = do
        f <- mf
        x <- mx
        return (f x)
      

      或者,脱糖:

      mf <*> mx =
        mf >>= \f ->
        mx >>= \x ->
        return (f x)
      

      多田!这可以作为Control.Monad.ap 使用,因此我们可以为任何单子M 提供FunctorApplicative 的完整实例,如下所示:

      instance Functor M where
        fmap = liftM
      
      instance Applicative M where
        pure = return
        (<*>) = ap
      

      理想情况下,我们可以直接在 Monad 中指定这些实现,以减轻为每个 monad 定义单独实例的负担,例如使用 this proposal。如果发生这种情况,使Applicative 成为Monad 的超类将没有真正的障碍,因为它将确保它不会破坏任何现有代码。另一方面,这意味着为给定的Monad 定义FunctorApplicative 实例所涉及的样板是最少的,因此很容易成为“好公民”(并且应该为任何单子定义这样的实例)。

      【讨论】:

      • 这个答案缺少一个重要的部分:证明如果给定的 Monad 实例 m 确实满足单子定律,那么您为 fmappure(&lt;*&gt;) 遵守 Functor 和 Applicative 法则。 Haskell 强制执行的只是类型检查。
      猜你喜欢
      • 2015-02-06
      • 1970-01-01
      • 1970-01-01
      • 2018-04-21
      • 1970-01-01
      • 1970-01-01
      • 2015-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多