タイプを比較すると
(<*>) :: Applicative a => a (s -> t) -> a s -> a t
(>>=) :: Monad m => m s -> (s -> m t) -> m t
2つの概念を区別する手がかりがわかります。(s -> m t)
のタイプのそれは、(>>=)
の値s
がの計算の動作を決定できることを示していますm t
。モナドは、値と計算層の間の干渉を可能にします。(<*>)
オペレータは、このような干渉を許容しない:関数引数の計算は、値に依存しません。これは本当に噛みます。比較する
miffy :: Monad m => m Bool -> m x -> m x -> m x
miffy mb mt mf = do
b <- mb
if b then mt else mf
いくつかの効果の結果を使用して、2つの計算(たとえば、ミサイルの発射と休戦への署名)を決定しますが、
iffy :: Applicative a => a Bool -> a x -> a x -> a x
iffy ab at af = pure cond <*> ab <*> at <*> af where
cond b t f = if b then t else f
それらの値を使用するab
との間で選択するために値 2つの計算at
とaf
の両方、恐らく悲劇的な影響を行う有します。
モナディックバージョンは(>>=)
、の値から計算を選択するという追加の能力に本質的に依存しており、それは重要な場合があります。ただし、その力をサポートすると、モナドを構成するのが難しくなります。「ダブルバインド」を構築しようとすると
(>>>>==) :: (Monad m, Monad n) => m (n s) -> (s -> m (n t)) -> m (n t)
mns >>>>== f = mns >>-{-m-} \ ns -> let nmnt = ns >>= (return . f) in ???
ここまで到達しましたが、今ではレイヤーがすべて乱雑になっています。を持っているn (m (n t))
ので、外側を取り除く必要がありn
ます。Alexandre Cが言うように、適切なものがあれば
swap :: n (m t) -> m (n t)
n
内側を入れ替え、join
他の入れ替えをするn
。
弱い「二重適用」は定義がはるかに簡単です
(<<**>>) :: (Applicative a, Applicative b) => a (b (s -> t)) -> a (b s) -> a (b t)
abf <<**>> abs = pure (<*>) <*> abf <*> abs
レイヤー間の干渉がないためです。
Monad
同様に、いつsの追加のパワーが本当に必要なのか、いつApplicative
サポートする厳密な計算構造で問題を回避できるのかを認識するのは良いことです。
ちなみに、モナドの作成は難しいですが、必要以上に多いかもしれません。タイプm (n v)
で計算を示しm
次いでコンピューティング、効果- n
の効果- v
-value、m
前効果-が完了n
効果-は、(用したがって必要開始しますswap
)。m
-effectsとn
-effects を交互に挿入したいだけの場合、コンポジションは多すぎて質問できないでしょう