类别类MonadPlus,Alternative和Monoid之间的区别?
标准库Haskelltypes类MonadPlus
, Alternative
和Monoid
每个都提供两种基本相同的语义:
- 空值:
mzero
,empty
或mempty
。 - 运算符
a -> a -> a
将mplus
中的值连接在一起:mplus
,<|>
或mappend
。
所有这三个都规定了这些实例应遵守的法律:
mempty `mappend` x = x x `mappend` mempty = x
因此,三个types类似乎都提供了相同的方法。
( Alternative
也提供了some
和many
,但是它们的默认定义通常是足够的,所以它们在这个问题上不是太重要。)
所以,我的问题是:为什么有这三个极其相似的类? 他们之间有什么真正的区别,除了他们不同的超类限制吗?
MonadPlus
和Monoid
服务于不同的目的。
Monoid
是通过一种types*
参数化的。
class Monoid m where mempty :: m mappend :: m -> m -> m
所以它可以被实例化为几乎任何types,有一个显而易见的运算符是关联的,它有一个单位。
然而, MonadPlus
不仅指定你有一个monoidal结构,而且这个结构与Monad
工作方式有关, 而且这个结构并不关心monad中包含的值,这是(部分地)用MonadPlus
需要参数types* -> *
。
class Monad m => MonadPlus m where mzero :: ma mplus :: ma -> ma -> ma
除了幺半律之外,我们还有两套适用于MonadPlus
潜在MonadPlus
。 可悲的是,社会不同意他们应该是什么。
至less我们知道
mzero >>= k = mzero
但是还有另外两个相互竞争的扩展,即左派(sic)分配法则
mplus ab >>= k = mplus (a >>= k) (b >>= k)
和左捉法
mplus (return a) b = return a
所以MonadPlus
任何实例MonadPlus
应该满足其中一个或两个附加的法则。
那么Alternative
呢?
Applicative
是在Monad
之后定义的,在逻辑上属于Monad
的超类,但很大程度上归因于Haskell 98中devise者的不同压力,甚至Functor
在2015年之前都不是Monad
的超类。现在我们终于有了Applicative
作为超类GHC中的Monad
(如果还没有达到语言标准的话)
MonadPlus
对于Monad
,有效的Alternative
是适用于MonadPlus
。
对于这些我们会得到
empty <*> m = empty
类似于我们对MonadPlus
所具有的MonadPlus
并且存在类似的分配和捕获属性,至less应该满足其中的一个。
不幸的是,即使是empty <*> m = empty
法律也太强大了。 例如,它不适用于Backwards 。
当我们看MonadPlus的时候,空的>> = f =空的法则几乎被强迫在我们身上。 无论如何,空的结构不能有任何“a”来调用函数f
。
但是,由于Applicative
不是 Monad
的超类, Alternative
不是 MonadPlus
的超类, MonadPlus
我们分别定义了两个实例。
而且,即使Applicative
是Monad
的超类,无论如何,即使我们服从了MonadPlus
类,
empty <*> m = empty
这并不足以certificate这一点
empty >>= f = empty
所以声称MonadPlus
东西比声称它是Alternative
更强。
现在按惯例,给定types的MonadPlus
和Alternative
应该同意,但Monoid
可能完全不同。
例如, MonadPlus
和Alternative
可以做到这一点:
instance MonadPlus Maybe where mzero = Nothing mplus (Just a) _ = Just a mplus _ mb = mb
但Monoid
实例将半群提升为Monoid
。 令人遗憾的是,因为当时在Haskell 98中不存在一个Semigroup
类,所以它通过请求一个Monoid
,而不是使用它的单元。 ಠ_ಠ
instance Monoid a => Monoid (Maybe a) where mempty = Nothing mappend (Just a) (Just b) = Just (mappend ab) mappend Nothing x = x mappend x Nothing = x mappend Nothing Nothing = Nothing
TL; DR MonadPlus
比Alternative
更强大,而Monoid
则比Monoid
更强大,而MonadPlus
和Alternative
types应该是相关的, Monoid
可能(有时是)完全不同的东西。