Arrows are exactly equivalent to applicative functors?

applicative, arrows, category-theory, haskell

Solution

Let's compare the IO applicative functor with the Kleisli arrows of the IO monad.

You can have an arrow that prints a value read by a previous arrow:

runKleisli ((Kleisli $ \() -> getLine) >>> Kleisli putStrLn) ()

But you can't do that with applicative functors. With applicative functors, all the effects take place before applying the function-in-the-functor to the arguments-in-the-functor. The function-in-the-functor can't use the value inside an argument-in-the-functor to "modulate" its own effect, so to speak.

Problem

According to the famous paper Idioms are oblivious, arrows are meticulous, monads are promiscuous, the expressive power of arrows (without any additional typeclasses) should be somewhere strictly between applicative functors and monads: monads are equivalent to `ArrowApply`, and `Applicative` should be equivalent to something the paper calls "static arrows". However, it is not clear to me what restriction this "static"-ness means. Playing around with the three typeclasses in question, I was able to build up an equivalence between applicative functors and arrows, which I present below in the context of the well-known equivalence between `Monad` and `ArrowApply`. Is this construction correct? (I've proven most of the arrow laws before getting bored of it). Doesn't that mean that `Arrow` and `Applicative` are exactly the same? ``` {-# LANGUAGE TupleSections, NoImplicitPrelude #-} import Prelude (($), const, uncurry) -- In the red corner, we have arrows, from the land of * -> * -> * import Control.Category import Control.Arrow hiding (Kleisli) -- In the blue corner, we have applicative functors and monads, -- the pride of * -> * import Control.Applicative import Control.Monad -- Recall the well-known result that every monad yields an ArrowApply: newtype Kleisli m a b = Kleisli{ runKleisli :: a -> m b} instance (Monad m) => Category (Kleisli m) where id = Kleisli return Kleisli g . Kleisli f = Kleisli $ g <=< f instance (Monad m) => Arrow (Kleisli m) where arr = Kleisli . (return .) first (Kleisli f) = Kleisli $ \(x, y) -> liftM (,y) (f x) instance (Monad m) => ArrowApply (Kleisli m) where app = Kleisli $ \(Kleisli f, x) -> f x -- Every arrow arr can be turned into an applicative functor -- for any choice of origin o 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) -- Arrplicatives over ArrowApply are monads, even instance (ArrowApply arr) => Monad (Arrplicative arr o) where return = pure Arrplicative ax >>= f = Arrplicative $ (ax >>> arr (runArrplicative . f)) &&& id >>> app -- Every applicative functor f can be turned into an arrow?? 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 ```

Original source

Related problems