类别类MonadPlus,Alternative和Monoid之间的区别?

标准库Haskelltypes类MonadPlusAlternativeMonoid每个都提供两种基本相同的语义:

  • 空值: mzeroemptymempty
  • 运算符a -> a -> amplus中的值连接在一起: mplus<|>mappend

所有这三个都规定了这些实例应遵守的法律:

 mempty `mappend` x = x x `mappend` mempty = x 

因此,三个types类似乎都提供了相同的方法。

Alternative也提供了somemany ,但是它们的默认定义通常是足够的,所以它们在这个问题上不是太重要。)

所以,我的问题是:为什么有这三个极其相似的类? 他们之间有什么真正的区别,除了他们不同的超类限制吗?

MonadPlusMonoid服务于不同的目的。

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我们分别定义了两个实例。

而且,即使ApplicativeMonad的超类,无论如何,即使我们服从了MonadPlus类,

 empty <*> m = empty 

这并不足以certificate这一点

 empty >>= f = empty 

所以声称MonadPlus东西比声称它是Alternative更强。

现在按惯例,给定types的MonadPlusAlternative应该同意,但Monoid可能完全不同。

例如, MonadPlusAlternative可以做到这一点:

 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 MonadPlusAlternative更强大,而Monoid则比Monoid更强大,而MonadPlusAlternativetypes应该是相关的, Monoid可能(有时是)完全不同的东西。