答えは次のとおりです(これはすべてControl.Arrow docsからのものです)
newtype ArrowApply a => ArrowMonad a b = ArrowMonad (a () b)
instance Monad ArrowApply a => Monad (ArrowMonad a)
newtype は、矢印のインスタンスArrowMonadを定義する手段です。使用できたはずですMonadArrowApply
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によって与えられます。観察:MonadMonadKleisli
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)
前のものは、モナド操作を使用した通常のすべてのアロー操作の実装を提供します。および を(***)使用するデフォルトの実装があるため、言及されていません。firstsecond
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とArrowMonadnewtypesによく反映されています。
newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }
newtype ArrowApply a => ArrowMonad a b = ArrowMonad (a () b)
にKleisliソース タイプを追加する必要がaあり、ArrowMonadに設定し()ます。
これがあなたを満足させることを願っています!