Aquí está la publicación SO a la que me referiré . Además, voy a usar los mismos fragmentos que el OP en esa pregunta para no separar los materiales .
Es ampliamente conocido que una ArrowApply
instancia produce una mónada y viceversa:
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))
Y hasta que me topé con la publicación mencionada anteriormente, sentí que este fragmento era una prueba plausible de la equivalencia de ArrowApply
y las Monad
clases. Sin embargo, tener el conocimiento de que Arrow y Applicative no son, de hecho, equivalentes y el siguiente fragmento me hizo sentir curiosidad acerca de la prueba completa de equivalencia de Monad
y 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
> Por lo tanto, si realiza un viaje de ida y vuelta a través de aplicativo, pierde algunas características.
Es obvio si se proporcionan los ejemplos, pero no entiendo cómo es que el "viaje de ida y vuelta" a través de Monad conserva todas las características de ArrowApply, ya que inicialmente teníamos una flecha que depende de alguna entrada ( a b c
) pero al final, terminamos con una flecha forzada en un contenedor que tiene el tipo de unidad como su tipo de entrada ( ArrowMonad (a () b)
).
Es obvio que estoy haciendo algo terriblemente mal aquí, pero no puedo entender exactamente qué.
¿Cuál es la prueba completa de que ArrowApply
y Monad
son equivalentes?
¿Qué explican los ejemplos de desigualdad de Arrow
y Applicative
? ¿Uno generaliza a otro?
¿Cuál es la interpretación de toda esa situación en el cálculo de flechas y la teoría de categorías?
Agradecería tanto las explicaciones completas como los consejos que podrían ayudarnos a elaborar una prueba plausible.