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
,所以我们可以给一个完整的实例Functor
和Applicative
任何单子M
如下:
instance Functor M where
fmap = liftM
instance Applicative M where
pure = return
(<*>) = ap
Run Code Online (Sandbox Code Playgroud)
理想情况下,我们可以直接指定这些实现Monad
,以减轻为每个monad定义单独实例的负担,例如使用此提议.如果发生这种情况,那么制作Applicative
超类就没有真正的障碍Monad
,因为它会确保它不会破坏任何现有的代码.另一方面,这意味着参与定义Functor
和Applicative
给定实例的样板Monad
是最小的,因此很容易成为"好公民"(并且应该为任何monad定义此类实例).