MonadPlus
并Monoid
达到不同的目的。
Monoid
通过类型的类型对A进行参数化*
。
class Monoid m where
mempty :: m
mappend :: m -> m -> m
因此,几乎可以将任何类型的实例化,只要有明显的关联运算符并且具有单位的运算符即可。
但是,MonadPlus
不仅指定您具有一个单曲面结构,而且该结构与Monad
工作方式相关,并且该结构不关心单子中包含的值,事实(部分)表明了这一点。这MonadPlus
需要一种争论* -> *
。
class Monad m => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a
除了monoid法则,我们还有两套可能适用的法则MonadPlus
。令人遗憾的是,社区对于应该成为什么样的人持不同意见。
至少我们知道
mzero >>= k = mzero
但是还有另外两个相互竞争的扩展,即左(原文如此)分布定律
mplus a b >>= k = mplus (a >>= k) (b >>= k)
和左捕捉法则
mplus (return a) b = return a
因此,任何实例MonadPlus
都应满足这些附加法律中的一个或两个。
那又如何Alternative
呢?
Applicative
是在之后定义的Monad
,并且在逻辑上属于的超类Monad
,但是很大程度上是由于Haskell 98中对设计师的压力不同,甚至直到2015Functor
年才成为超类Monad
。现在,我们终于在GHC中Applicative
成为超类Monad
(如果没有,还是语言标准)。
实际上,Alternative
是Applicative
什么MonadPlus
是Monad
。
对于这些,我们会得到
empty <*> m = empty
与我们拥有的类似,MonadPlus
并且存在类似的分发和捕获属性,您至少应满足其中之一。
不幸的是,即使empty <*> m = empty
法律也没有足够的主张。例如,它不适用于Backwards!
当我们查看MonadPlus时,几乎要强制执行空>> = f =空定律。无论如何,空构造不能包含任何“ a”来调用函数f
。
但是,由于Applicative
是没有的超类Monad
和Alternative
是不是一个超类MonadPlus
,我们拉闸分别定义两个实例。
而且,即使Applicative
是的超类Monad
,您仍然会需要MonadPlus
该类,因为即使我们遵守了
empty <*> m = empty
这还不足以证明
empty >>= f = empty
因此,宣称某物为aMonadPlus
比声称其为有力Alternative
。
现在,按照约定,给定类型的MonadPlus
和Alternative
应当达成共识,但Monoid
可能完全不同。
例如,MonadPlus
and Alternative
forMaybe
做显而易见的事情:
instance MonadPlus Maybe where
mzero = Nothing
mplus (Just a) _ = Just a
mplus _ mb = mb
但Monoid
实例将一个半群提升为Monoid
。可悲的是,由于Semigroup
Haskell 98当时不存在一个类,因此它通过请求aMonoid
而不是使用其单元来实现。ಠ_ಠ
instance Monoid a => Monoid (Maybe a) where
mempty = Nothing
mappend (Just a) (Just b) = Just (mappend a b)
mappend Nothing x = x
mappend x Nothing = x
mappend Nothing Nothing = Nothing
TL; DR MonadPlus
是比更有力的主张Alternative
,而在TL; DR则是有力的主张Monoid
,并且虽然类型的MonadPlus
和Alternative
实例应该相关,但Monoid
可能(有时是)完全不同。
Applicative
和MonadPlus
似乎完全相同(模超类约束)。