答えは次のとおりです(これはすべてControl.Arrow docsからのものです)
newtype ArrowApply a => ArrowMonad a b = ArrowMonad (a () b)
instance Monad ArrowApply a => Monad (ArrowMonad a)
newtype は、矢印のインスタンスArrowMonad
を定義する手段です。使用できたはずですMonad
ArrowApply
instance Monad ArrowApply a => Monad (a ())
しかし、これは Haskell の制限された型クラスの推論で問題を引き起こしたでしょう (それはUndecideableInstances
拡張機能で動作するだろうと私は推測しています)。
ソースが示すように、矢印のMonad
インスタンスは、モナド操作を同等の矢印操作に変換するものと考えることができます。ArrowApply
instance ArrowApply a => Monad (ArrowMonad a) where
return x = ArrowMonad (arr (\_ -> x))
ArrowMonad m >>= f = ArrowMonad (m >>>
arr (\x -> let ArrowMonad h = f x in (h, ())) >>>
app)
そのため、すべての操作を実装できるため、これは非常に強力であることArrowApply
がわかっています。驚くべきことに、その逆も成り立ちます。@hammarが指摘したように、これはnewtypeによって与えられます。観察:Monad
Monad
Kleisli
newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }
instance Monad m => Category (Kleisli m) where
id = Kleisli return
(Kleisli f) . (Kleisli g) = Kleisli (\b -> g b >>= f)
instance Monad m => Arrow (Kleisli m) where
arr f = Kleisli (return . f)
first (Kleisli f) = Kleisli (\ ~(b,d) -> f b >>= \c -> return (c,d))
second (Kleisli f) = Kleisli (\ ~(d,b) -> f b >>= \c -> return (d,c))
instance Monad m => ArrowApply (Kleisli m) where
app = Kleisli (\(Kleisli f, x) -> f x)
instance Monad m => ArrowChoice (Kleisli m) where
left f = f +++ arr id
right f = arr id +++ f
f +++ g = (f >>> arr Left) ||| (g >>> arr Right)
Kleisli f ||| Kleisli g = Kleisli (either f g)
前のものは、モナド操作を使用した通常のすべてのアロー操作の実装を提供します。および を(***)
使用するデフォルトの実装があるため、言及されていません。first
second
f *** g = first f >>> second g
これで、 Monad 操作を使用して矢印 ( Arrow
、ArrowChoice
、 ) 操作を実装する方法がわかりました。ArrowApply
Monad
両方を持っている理由とArrow
、それらが同等であることが判明したかどうかについてのあなたの質問に答えるには:
弱いアローは、アプリカティブ ファンクタが有用であるのと同様に、モナドのフル パワーを必要としない場合に有用です。そして、ArrowApply
とMonad
は同等ですが、Arrow
またはArrowChoice
なしapp
は、Monad
階層で表現できないものです。逆に、Applicative
は矢印階層で表現できません。これはap
、モナド階層では「最初」、アロー階層では「最後」になるためです。
モナドとアローの世界の主な意味上の違いは、アローは変換をキャプチャする (arr b c
つまり、 ac
からを生成するb
) のに対し、モナドは操作をキャプチャする (monad a
を生成するa
) ことです。この違いは、Kleisli
とArrowMonad
newtypesによく反映されています。
newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }
newtype ArrowApply a => ArrowMonad a b = ArrowMonad (a () b)
にKleisli
ソース タイプを追加する必要がa
あり、ArrowMonad
に設定し()
ます。
これがあなたを満足させることを願っています!