En programación funcional , un funtor aplicativo , o un aplicativo para abreviar, es una estructura intermedia entre los funtores y las mónadas . En teoría de categorías se denominan funtores monoidales cerrados. Los funtores aplicativos permiten que los cálculos funtoriales se ordenen en secuencia (a diferencia de los funtores simples), pero no permiten utilizar los resultados de los cálculos anteriores en la definición de los posteriores (a diferencia de las mónadas). Los funtores aplicativos son el equivalente en programación de los funtores monoidales laxos con fuerza tensorial en la teoría de categorías .
Los funtores aplicativos fueron introducidos en 2008 por Conor McBride y Ross Paterson en su artículo Programación aplicativa con efectos . [1]
Los funtores aplicativos aparecieron por primera vez como una característica de la biblioteca en Haskell , pero desde entonces se han extendido también a otros lenguajes, incluidos Idris , Agda , OCaml , Scala y F# . Glasgow Haskell, Idris y F# ofrecen características del lenguaje diseñadas para facilitar la programación con funtores aplicativos. En Haskell, los funtores aplicativos se implementan en la Applicative
clase de tipo.
Si bien en lenguajes como Haskell las mónadas son funtores aplicativos, no siempre es así en entornos generales de teoría de categorías: se pueden encontrar ejemplos de mónadas que no son fuertes en Math Overflow.
En Haskell, un aplicativo es un tipo parametrizado que consideramos como un contenedor para datos del tipo de parámetro más dos métodos pure
y <*>
. El pure
método para un aplicativo de tipo parametrizado f
tiene tipo
puro :: a -> f a
y puede considerarse como la incorporación de valores al aplicativo. El <*>
método para un aplicativo de tipo f
tiene tipo
( <*> ) :: f ( a -> b ) -> f a -> f b
y puede considerarse como el equivalente de la función aplicación dentro del aplicativo. [2]
Como alternativa, en lugar de proporcionar <*>
, se puede proporcionar una función llamada liftA2
. Estas dos funciones pueden definirse una en términos de la otra; por lo tanto, solo se necesita una para una definición mínimamente completa. [3]
También se requiere que los aplicativos satisfagan cuatro leyes ecuacionales: [3]
pure id <*> v = v
pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
pure f <*> pure x = pure (f x)
u <*> pure y = pure ($ y) <*> u
Todo aplicativo es un funtor. Para ser explícito, dados los métodos pure
y <*>
, fmap
se puede implementar como [3]
fmap g x = g puro <*> x
La notación comúnmente utilizada es equivalente a .g <$> x
pure g <*> x
En Haskell, el tipo Maybe se puede convertir en una instancia de la clase de tipo Applicative
utilizando la siguiente definición: [2]
instancia Aplicativo Quizás donde -- puro :: a -> Quizás un puro a = Solo un -- (<*>) :: Tal vez (a -> b) -> Tal vez a -> Tal vez b Nada <*> _ = Nada _ <*> Nada = Nada ( Solo g ) <*> ( Solo x ) = Solo ( g x )
Como se indica en la sección Definición, pure
convierte un a
en un y aplica una función Maybe a un valor Maybe. El uso del aplicativo Maybe para el tipo permite operar con valores del tipo y el error se maneja automáticamente por la maquinaria aplicativa. Por ejemplo, para sumar y , solo se necesita escribirMaybe a
<*>
a
a
m :: Maybe Int
n :: Maybe Int
( + ) <$> m <*> n
En el caso en que no hay error, al sumar y se obtiene . Si cualquiera de o es , entonces el resultado también será . Este ejemplo también demuestra cómo los aplicativos permiten una especie de aplicación de función generalizada.m=Just i
n=Just j
Just(i+j)
m
n
Nothing
Nothing