Here's the SO post I'm going to refer to. Also, I'm going to use the same snippets as the OP in that question in order not to separate the materials.
It is widely known that an ArrowApply
instance yields a Monad and vice versa:
newtype ArrowMonad a b = ArrowMonad (a () b)
instance Arrow a => Functor (ArrowMonad a) where
fmap f (ArrowMonad m) = ArrowMonad $ m >>> arr f
instance Arrow a => Applicative (ArrowMonad a) where
pure x = ArrowMonad (arr (const x))
ArrowMonad f <*> ArrowMonad x = ArrowMonad (f &&& x >>> arr (uncurry id))
instance ArrowApply a => Monad (ArrowMonad a) where
ArrowMonad m >>= f = ArrowMonad $
m >>> arr (\x -> let ArrowMonad h = f x in (h, ())) >>> app
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))
And until I've stumbled upon the post referenced above, I felt that this snippet was a plausible proof for the equivalence of ArrowApply
and Monad
classes. Yet, having the knowledge that Arrow and Applicative are not, in fact, equivalent and the following snippet made me curious about the full proof of equivalency of Monad
and ArrowApply
:
newtype Arrplicative arr o a = Arrplicative{ runArrplicative :: arr o a }
instance (Arrow arr) => Functor (Arrplicative arr o) where
fmap f = Arrplicative . (arr f .) . runArrplicative
instance (Arrow arr) => Applicative (Arrplicative arr o) where
pure = Arrplicative . arr . const
Arrplicative af <*> Arrplicative ax = Arrplicative $
arr (uncurry ($)) . (af &&& ax)
newtype Applicarrow f a b = Applicarrow{ runApplicarrow :: f (a -> b) }
instance (Applicative f) => Category (Applicarrow f) where
id = Applicarrow $ pure id
Applicarrow g . Applicarrow f = Applicarrow $ (.) <$> g <*> f
instance (Applicative f) => Arrow (Applicarrow f) where
arr = Applicarrow . pure
first (Applicarrow f) = Applicarrow $ first <$> f
Thus if you round trip through applicative you lose some features.
It is obvious with the examples written down, yet I fail to grasp how is "round-tripping" through Monad preserves all the ArrowApply features since initially we had an arrow which depends on some input (a b c
) but in the end, we end up with an arrow forced into a wrapper which has unit type as its input type (ArrowMonad (a () b)
).
It is obvious that I'm doing something awfully wrong here, yet I cannot understand what exactly.
What is the full proof that ArrowApply
and Monad
are equivalent?
What do the examples of inequivalence of Arrow
and Applicative
account for? Does one generalise another?
What is the interpretation of that whole situation in arrow calculus and category theory?
I would appreciate both full explanations and tips which could help one draw up a plausible piece of proof themself.