型クラスMonadPlus、Alternative、Monoidの違いは?


83

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

  • 空の値:mzeroempty、またはmempty
  • オペレータa -> a -> a:一緒に型クラスの値を結合しmplus<|>またはmappend

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

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

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

Alternativeも提供someしてmany、彼らのデフォルトの定義は、通常は十分であるので、彼らはこの質問の面であまり重要ではないです。)

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


それは良い質問です。特に、ApplicativeおよびMonadPlusように見える、正確に同じ(モジュロスーパー制約)。
ピーター

1
ArrowZeroArrowPlus矢印もあります。私の賭け:型シグネチャをよりクリーンにすること(これにより、異なるスーパークラス制約実際の違いになります)。
Cat Plus Plus

2
@CatPlusPlus:まあ、ArrowZeroArrowPlus親切持って* -> * -> *あなたはニーズが使用する、種類の多数のためにそれらを使用することを関数に一度矢印タイプのためにそれらを通過することができる手段、Monoidあなたがのインスタンス必要とする必要があると思いますMonoidそれぞれの特定のためにインスタンス化、およびそれらが同様の方法で処理されたという保証はありません。インスタンスは無関係である可能性があります。
エドワードKMETT 2012

回答:


120

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しても、しかし、主にバックハスケル98でデザイナーの異なる圧力へFunctorのスーパーではなかったMonad2015年は、今、私たちは最終的に持っているまでApplicativeのスーパークラスとしてMonad(ない場合はGHCでまだ言語標準です。)

事実上、何AlternativeをするApplicativeMonadPlusですMonad

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

empty <*> m = empty

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

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

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

しかし、ApplicativeあるではないのスーパークラスMonadAlternativeされていないのスーパーMonadPlus、我々は別に両方のインスタンスを定義する羽目になる。

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

empty <*> m = empty

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

empty >>= f = empty

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

さて、慣例により、MonadPlusおよびAlternative特定のタイプのためには同意する必要がありますが、Monoidかもしれ全く異なります。

例えばMonadPlusAlternativeのためのMaybe明白なことを実行します。

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

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

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は完全に異なるものである可能性があります(場合によってはそうである場合もあります)。


2
素晴らしい答えですが、最後の定義が間違っているようですが、それは満足していませんmempty `mappend` x ≡ x
Vitus 2012

2
素晴らしい答え。持っている(一般的に使用される)タイプの誰も知っている異なる MonadPlusAlternative実装を?
ピーター

7
@EdwardKmett:この回答Monadは、であるAlternativeがではないが存在する可能性があることを示唆しているようMonadPlusです。私はこれの特定の例を見つけることについて質問しました。あなたがそれを知っているなら、私はそれを見たいです。
アンタルスペクター-ザブスキー2012年

2
モナドプラスの左翼法について説明していただけますか?[]によって明らかに違反されています。最初の引数が空でない場合、[]は2番目の引数を本当に無視する必要がありますか?
ben w

4
@benwの左分布は、間違いなくより賢明な法則ですが、場合によっては当てはまりません。左キャッチは、他のインスタンスがサポートする傾向があるが、他のほとんどのインスタンスではサポートされていない代替法です。その結果、実際には2つのほとんど関係のない一連の法則が異なるインスタンスによって実装されているMonadPlusため、ほとんどの人が気にしないため、実際には2つのクラスが1つに偽装されています。
エドワードKMETT 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.