多くのApplicativeもモナドであるため、この質問には本当に2つの側面があると思います。
両方が利用可能なのに、なぜモナディックインターフェイスの代わりにアプリケーションインターフェイスを使用したいのですか?
これは主にスタイルの問題です。モナドにはdo
-notationの構文糖衣がありますが、適用可能なスタイルを使用すると、コードがよりコンパクトになることがよくあります。
この例では、タイプがFoo
あり、このタイプのランダムな値を作成します。のモナドインスタンスを使用してIO
、次のように記述します。
data Foo = Foo Int Double
randomFoo = do
x <- randomIO
y <- randomIO
return $ Foo x y
適用可能なバリアントはかなり短いです。
randomFoo = Foo <$> randomIO <*> randomIO
もちろん、liftM2
同様の簡潔さを得るために使用することもできますが、適用可能なスタイルは、アリティ固有のリフティング機能に依存する必要があるよりも優れています。
実際には、ポイントフリースタイルを使用するのとほとんど同じ方法でApplicativeを使用しています。操作が他の操作の構成としてより明確に表現されている場合に、中間値に名前を付けないようにするためです。
モナドではないアプリケーションを使用したいのはなぜですか?
Applicativeはモナドよりも制限されているため、これは、Applicativeに関するより有用な静的情報を抽出できることを意味します。
この例は、アプリケーションパーサーです。モナディックパーサーはを使用したシーケンシャルコンポジションをサポートし(>>=) :: Monad m => m a -> (a -> m b) -> m b
ますが、アプリケーションパーサーはを使用するだけ(<*>) :: Applicative f => f (a -> b) -> f a -> f b
です。タイプによって違いが明らかになります。モナディックパーサーでは、入力に応じて文法が変わる可能性がありますが、アプリケーションパーサーでは、文法が固定されています。
このようにインターフェイスを制限することで、たとえば、パーサーが空の文字列を実行せずに受け入れるかどうかを判断できます。また、最適化に使用できる最初のセットと次のセットを決定することも、最近遊んでいるように、より優れたエラー回復をサポートするパーサーを構築することもできます。