Me gustaría tener una función para asignar una función pura a un contenedor o secuenciar la acción aplicativa/monádica a través de ella. Para el mapeo pura tenemosFunctor es para (a -> b) -> (f a -> f b), ¿qué es para (Categoría c) => c a b -> c (f a) (f b)?
fmap :: Functor f => (a -> b) -> (f a -> f b)
Para la secuenciación monádico tenemos (de Data.Taversable)
mapM :: (Traversable f, Monad m) => (a -> m b) -> (f a -> m (f b))
que es similar a
mapKleisli :: (Traversable f, Monad m) => Kleisli m a b -> Kleisli m (f a) (f b)
mapKleisli = Kleisli . mapM . runKleisli
Sabemos tanto (->) y (Kleisli m) son categorías (y flechas). Por lo tanto, es natural hacer una generalización:
mapCategory :: (X f, Category c) => c a b -> c (f a) (f b)
¿Conocen esa clase X con un método similar? Tal vez, en algún lugar en Hackage? Intenté hoogle/hayoo pero no encontré nada apropiado.
Actualización:
Ahora sé mejor lo que necesito. Tanto las flechas Kleisli como (->) son instancias de ArrowApply que es tan poderoso como Monad. Se me ocurrió con esta versión basada en la flecha de Travesable:
{-# LANGUAGE TypeOperators #-}
import Prelude hiding (id, (.), mapM)
import Control.Arrow
import Control.Category
class Traversable f where
traverse :: ArrowApply (~>) => f a -> (a ~> b) ~> f b
mapArrow :: (ArrowApply (~>), Traversable f) => a ~> b -> f a ~> f b
mapArrow a = arr (\x -> (traverse x, a)) >>> app
instance Traversable Maybe where
traverse Nothing = arr (const Nothing)
traverse (Just x) = arr (\a -> (a, x)) >>> app >>> arr Just
instance Traversable [] where
traverse [] = arr (const [])
traverse (x : xs) = undefined -- this is hard!
que podría utilizar simplemente habitual basada en Aplicativo de Traversable, la identidad de funciones puras, pero no estoy seguro de que es buena. Considerar funciones puras como un caso especial de acciones monádicas es extraño. Interpretar funciones puras y monádicas como instancias de alguna clase de acción (Category/Arrow/ArrowApply) me parece más directo.
Preguntas: ¿quieres terminar la instancia para []
? ¿Tiene mi opinión sobre ArrowApply vs Monad algún sentido?
Gracias por la respuesta, pero en este caso tengo más interés práctico que teórico. [En paquete de categorías] (http://hackage.haskell.org/packages/archive/categories/0.56.0/doc/html/Control-Categorical-Functor.html) solo tenemos instancias (Endo) Functor para (->) categoría que no nos da nada nuevo en comparación con lo que tenemos en la base (excepto la clase misma). – modular
@ user713303: puede escribir sus propias instancias. Por ejemplo, sería muy sencillo hacerlo con las flechas Kleisli, como lo demostró en su pregunta. –
De hecho, si tiene instancias prácticas y útiles en mente, ¿por qué no contribuir con ellas? Aquí está [la página de github] (https://github.com/ekmett/categories) para el paquete. –