2011-06-22 34 views
15

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?

Respuesta

10

Está pidiendo "alguna clase X", pero debe quedar bastante claro que el nombre correcto (o tal vez, único) para esta clase sería "Functor". Lo que desea es simplemente una clase ficticia definida para una instancia arbitraria de Category, en lugar de limitarse a (->).

Por supuesto, su definición todavía está limitada a (endo) functors de una categoría a una subcategoría definida por el constructor de tipo que da la instancia. Si se generaliza un poco más lejos, no hay razón para las dos categorías a ser la misma, dándole a type class something like this one:

class (Category r, Category t) => Functor f r t | f r -> t, f t -> r where 
    fmap :: r a b -> t (f a) (f b) 

Esto es todavía muy limitada contra el concepto completo de un funtor en la teoría de categorías, pero bueno .

También es interesante observar que todavía tiene un constructor de tipo (->), eso es porque, aunque estamos modelando las categorías de origen y destino con instancias arbitrarias, todo (y, en particular, el propio functor)) todavía existe en algún sentido en Hask, es decir, la categoría asociada con (->). La otra mitad del functor (los objetos de mapeo de la parte) es, aproximadamente, el (->) en el tipo * -> * para el constructor de tipo f.

+0

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

+0

@ user713303: puede escribir sus propias instancias. Por ejemplo, sería muy sencillo hacerlo con las flechas Kleisli, como lo demostró en su pregunta. –

+1

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. –

Cuestiones relacionadas