ejemplos - funciones en haskell
¿Qué es exactamente un functor indexado en Haskell y cuáles son sus usos? (1)
Al estudiar los funtores en Haskell se me ocurrió el tipo de funtor Functor.Indexed . Este functor define una operación llamada imap
. No entendí su definición y firma de imap
: imap :: (a -> b) -> fjka -> fjkb
. Intenté encontrar su definición formal y solo encontré esto: http://ncatlab.org/nlab/show/indexed+functor . Pero realmente no me ayudó en absoluto. Entonces, ¿puede alguien aclarar con palabras más simples este tipo de funtor y en qué casos debería usarlo? Gracias.
Un funtor indexado es, para usar la redacción de spacesuitburritoesque espaciososesqueños, "un contenedor que también contiene un mapeo". Es decir, un valor fjka
"contendrá" algún tipo de morfismo (s) j -> k
(no necesariamente funciones, puede ser flechas más generales) y también valores de tipo a
.
Para aquellos valores, el contenedor es un functor de la manera obvia. De hecho, la clase IxFunctor
por sí sola es bastante aburrida, una
instance IxFunctor f
es básicamente lo mismo que
instance Functor (f j k)
Ahora, donde se pone interesante es cuando se consideran las clases de functor más específicas. Esta mónada no está realmente en el módulo Indexed
, pero creo que aclara mejor el punto:
class IxPointed f => IxMonad f where
ijoin :: m j k (m k l a) -> m j l a
compara esto lado a lado:
(>>>) :: (j->k) -> (k->l) -> j->l
ijoin :: m j k (m k l a) -> m j l a
join :: m (m a) -> m a
Entonces, lo que hacemos es, al unir las "capas de contenedor", componemos los morfismos.
El ejemplo obvio es IxState
. Recordemos la mónada estatal estándar
newtype State s a = State { runState :: s -> (a, s) }
Esto, cuando se usa como una mónada, simplemente compone el aspecto s -> s
de la función:
join (State f) = State $ /s -> let (State f'', s'') = f s in f'' s''
así que pasas el estado primero por f
, luego por f''
. Bueno, realmente no hay razón para que todos los estados tengan el mismo tipo, ¿verdad? Después de todo, el estado intermedio simplemente se pasa a la siguiente acción. Aquí está la mónada del estado indexado,
newtype IxState i j a = IxState { runIxState :: i -> (a, j) }
Simplemente hace eso:
ijoin (IxState f) = IxState $ /s -> let (IxState f'', s'') = f s in f'' s''