如何证明monad是一个仿函数和一个应用函子?

Kos*_*Kos 15 monads haskell functor applicative

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

知道这一点,给出一个monad并基于return以及bind如何:

  • 派生fmap,
  • 派生<*>

ehi*_*ird 26

嗯,fmap只是(a -> b) -> f a -> f b,即我们想用纯函数转换monadic动作的结果.用符号写起来很容易:

fmap f m = do
  a <- m
  return (f a)
Run Code Online (Sandbox Code Playgroud)

或者,写成"原始":

fmap f m = m >>= \a -> return (f a)
Run Code Online (Sandbox Code Playgroud)

这是可用的Control.Monad.liftM.

pure :: a -> f a当然是return.(<*>) :: f (a -> b) -> f a -> f b有点棘手.我们有一个返回一个函数的动作,一个返回其参数的动作,我们想要一个动作返回它的结果.再做一次记录:

mf <*> mx = do
  f <- mf
  x <- mx
  return (f x)
Run Code Online (Sandbox Code Playgroud)

或者,desugared:

mf <*> mx =
  mf >>= \f ->
  mx >>= \x ->
  return (f x)
Run Code Online (Sandbox Code Playgroud)

田田!这是作为Control.Monad.ap,所以我们可以给一个完整的实例FunctorApplicative任何单子M如下:

instance Functor M where
  fmap = liftM

instance Applicative M where
  pure = return
  (<*>) = ap
Run Code Online (Sandbox Code Playgroud)

理想情况下,我们可以直接指定这些实现Monad,以减轻为每个monad定义单独实例的负担,例如使用此提议.如果发生这种情况,那么制作Applicative超类就没有真正的障碍Monad,因为它会确保它不会破坏任何现有的代码.另一方面,这意味着参与定义FunctorApplicative给定实例的样板Monad是最小的,因此很容易成为"好公民"(并且应该为任何monad定义此类实例).

  • 这个答案缺少一个重要的部分:证明如果一个给定的`Monad`实例`m`确实满足Monad定律,那么你为`fmap`,`pure`和`(<*>)`提供的monadic定义服从Functor和Applicative法律.Haskell强制执行的所有操作都是类型检查. (5认同)

dav*_*420 10

fmap = liftM(<*>) = ap.以下是liftMap源代码的链接.我认为你知道如何desugar做符号.