90

標準ライブラリのHaskell型クラス、、、MonadPlusおよびAlternativeそれぞれMonoidは、本質的に同じセマンティクスを持つ2つのメソッドを提供します。

  • 空の値:mzero、、、emptyまたはmempty
  • a -> a -> aタイプクラスの値を結合する演算子: mplus、、、<|>またはmappend

3つすべてが、インスタンスが準拠する必要があるこれらの法則を指定します。

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

したがって、3つの型クラスはすべて同じメソッドを提供しているようです。

Alternativeとも提供somemanyますが、通常はデフォルトの定義で十分なので、この質問に関してはそれほど重要ではありません。)

だから、私の質問は:なぜこれらの3つの非常に似たクラスがあるのですか?スーパークラスの制約が異なること以外に、それらの間に実際の違いはありますか?

4

1 に答える 1

123

MonadPlusMonoidさまざまな目的を果たします。

AMonoidは、種類のタイプに対してパラメーター化されます*

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

モノイド法に加えて、適用できる法の2つの潜在的なセットがありますMonadPlus。悲しいことに、コミュニティは彼らがどうあるべきかについて意見が分かれています。

少なくとも私たちは知っています

mzero >>= k = mzero

しかし、他に2つの競合する拡張機能があります。それは、左(原文のまま)の分配法です。

mplus a b >>= k = mplus (a >>= k) (b >>= k)

と左キャッチ法

mplus (return a) b = return a

したがって、のインスタンスはMonadPlus、これらの追加の法則の一方または両方を満たす必要があります。

では、どうAlternativeですか?

Applicativeの後に定義されMonad、論理的にはのスーパークラスに属しますがMonad、主にHaskell 98に戻ったデザイナーへのさまざまな圧力のために、2015年までFunctorのスーパークラスではありませんでした。まだ言語標準です。)MonadApplicativeMonad

事実上、何Alternativeをするかです。ApplicativeMonadPlusMonad

これらのために私達は得るだろう

empty <*> m = empty

私たちが持っているものと同様に、MonadPlus同様の分配法則とキャッチ法則が存在し、少なくとも1つは満たす必要があります。

残念ながら、empty <*> m = empty法律でさえ主張が強すぎます。たとえば、 Backwardsには当てはまりません。

MonadPlusを見ると、空の>> =f=空の法則がほぼ強制されています。空の構造には、とにかく関数を呼び出すための「a」を含めることはできませfん。

ただし、はのスーパークラスではApplicativeなくのスーパークラスでもないため、両方のインスタンスを別々に定義することになります。MonadAlternativeMonadPlus

さらに、Applicativeのスーパークラスであったとしても、私たちが従ったとしても、とにかくクラスMonadが必要になるでしょう。MonadPlus

empty <*> m = empty

それはそれを証明するのに厳密には十分ではありません

empty >>= f = empty

したがって、何かがであると主張することは、MonadPlusそれがであると主張することよりも強力ですAlternative

さて、慣例により、与えられたタイプのMonadPlusAlternativeは一致するはずですが、Monoid完全に異なる場合があります。

たとえばMonadPlus、andforは明らかなことAlternativeを行います。Maybe

instance MonadPlus Maybe where
    mzero = Nothing
    mplus (Just a) _  = Just a
    mplus _        mb = mb

しかし、Monoidインスタンスは半群をに持ち上げますMonoidSemigroup悲しいことに、Haskell 98には当時クラスが存在していなかったためMonoid、そのユニットを使用せずに、を要求することで存在します。ಠ_ಠ</p>

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、これは、よりも強力な主張でありMonoid、型のインスタンスMonadPlusAlternativeインスタンスは関連している必要がありますが、Monoidは完全に異なるものである可能性があります(場合によってはそうである場合もあります)。

于 2012-04-16T02:36:32.283 に答える