人们说monad是应用函子的扩展,但我不是以应用函子为例: (<*>) :: f(a->b) -> f a -> f b
[(+3)] <*> [2,3,4]
现在,我也期望我可以做与monad相同的事情,这意味着我可以应用2个参数:一个上下文包含一个函数,另一个上下文来获取一个上下文 . 但对于monad,我不能 . 我需要的只是写一个像这样丑陋的函数:
[2,3,4] >>= (\x->[x+3])
是的,当然,你可以说 [(+3)]
相当于 [\x->(x+3)]
. 但至少,这个功能是在上下文中 .
最后,我在这里看不到等价或扩展 . Monad是另一种风格,在另一个故事中很有用 .
对不起我的无知 .
3 回答
如果
T
是Monad
的实例,那么您可以将它设为Applicative
的实例,如下所示:liftM
定义为ap
被定义为所以,"monads are an extension of applicative functors"在某种意义上说任何monad都可以成为一个应用程序 . 实际上,它被广泛(不是普遍地)认为是标准库中的一个错误,类
Monad
不是从类Applicative
派生的 .我认为它澄清了再次定义
<*>
的关系,但使用Monad:给出与
<*>
相同的结果:甚至
现在变量
f
和a
的存在以及>*>
定义中的最后一行是Monad和Applicative之间的 key difference . 在Applicative中,你最后只能return
,而在Monad中,你可以用f
和a
做任何你喜欢的事情 .相似之处
在Applicative中,你可以这样做
我们可以将其转换为Monad函数
或者更典型的是,
差异
在Monad,你可以做到
例如,
请注意
checkFirst
更改了我输入n
后发生的事情 - 它直接返回Nothing
而没有给我机会输入getLine
或按Enter键,而如果我从q
开始它继续运行getLine
. 这种改变在值的强度上完成的能力是Monad和Applicative之间的关键区别,但你可以看到>*>
运算符,Monad完成了Applicative所做的一切 . (它们都有return
,Applicative调用pure
,它们都有(<$>)
或fmap
,因为它们都是Functors . )你最接近在Applicative写作
checkFirst
是其工作方式如下:
(注意:由于Windows ghc bug in getChar,你无法区分windows中ghci中的
checkFirst
和don'tCheckFirst
之间的区别 . )摘要
Monad就像是Applicative,但有能力根据有什么 Value 完全改变你正在做的事情 .
Haskell中的monad是一个Applicative加
join
,即"flatten" monad的函数,join :: m (m a) -> m a
."Applicative application"
<*>
的类型为f (a -> b) -> f a -> f b
;如果您现在选择类型b
在同一个Functor中,即b :: f c
,则类型签名专门用于<*> :: f (a -> f c) -> f a -> f (f c)
. 当你不在这里做的时候;但是,使用monadicjoin
函数,你可以展平结果,获得与之前相同的monad中的某些东西(而不是双堆叠monad) .