Monad es un tipo de dato especial en lenguajes de programación funcional , para el cual es posible establecer una secuencia imperativa para realizar ciertas operaciones en valores almacenados [1] . Las mónadas le permiten establecer la secuencia de operaciones, realizar operaciones con efectos secundarios y otras acciones que son difíciles o imposibles de implementar en el paradigma de programación funcional de otras maneras.
El concepto y término de mónada proviene originalmente de la teoría de categorías , donde se define como un funtor con estructura adicional. La investigación que comenzó a fines de la década de 1980 y principios de la de 1990 estableció que las mónadas podían reunir problemas informáticos aparentemente dispares en un solo modelo funcional. La teoría de categorías también plantea varios requisitos formales.[ ¿Qué? ] , las llamadas leyes monádicas , que deben ser observadas por cualquier mónada y pueden utilizarse para verificar el código monádico.
Las mónadas se usan más comúnmente en lenguajes de programación funcionales . Con un modelo de evaluación perezoso, se desconoce el orden de reducción. Por ejemplo, el cálculo 1 + 3 + 6se puede reducir a 1 + 9o 4 + 6. Las mónadas permiten ordenar la reducción. Por lo tanto, hay una afirmación irónica de que las mónadas son una forma de sobrecargar el operador de punto y coma.
Una mónada es un contenedor que almacena un valor de un tipo arbitrario. Debe tener una función de vinculación que tome dos argumentos: el valor actual de la mónada y una función que tome un valor del tipo que contiene la mónada actual y devuelva la nueva mónada. El resultado de llamar a la función bind será una nueva mónada obtenida aplicando el primer argumento al segundo. Así es como podría verse una mónada en el lenguaje imperativo de Java y una de sus implementaciones, el contenedor Maybe:
importar java.util.function.Function ; interface Monad < T > { < U > Monad < U > bind ( Función < T , Monad < U >> f ); } class Maybe < T > implementa Monad < T > { privado final Tval ; _ public Tal vez ( T val ) { este . valor = valor ; } public T getVal () { return val ; } @Override public < U > Monad < U > bind ( Function < T , Monad < U >> f ) { if ( val == null ) return new Maybe < U > ( null ); volver f . aplicar ( val ); } } public class MonadApp { public static void main ( String [] args ) { Maybe < Integer > x = new Maybe <> ( 5 ); Mónada < Entero > y = x . enlazar ( v -> nuevo Tal vez <> ( v + 1 )) . bind ( v -> nuevo Quizás <> ( v * 2 )); sistema _ fuera _ println ( (( Quizás < Entero > ) y ). getVal () ); } }Las interfaces funcionales introducidas en Java 8 le permiten implementar una interfaz similar a una mónada.
La clase Monad está presente en el módulo estándar Prelude. La implementación de esta clase requiere cualquier tipo de un parámetro (tipo de género * -> *). La mónada tiene cuatro métodos.
clase Funtor f donde fmap :: ( a -> b ) -> f a -> f b class Functor f => Aplicativo f where pure :: a -> f a ( <*> ) :: f ( a -> b ) -> f a -> f b ( *> ) :: f a -> f b -> f segundo ( <* ) :: fa - > f segundo - > fa -- m :: * -> * clase Aplicativo m => Mónada m donde ( >>= ) :: m a -> ( a -> m b ) -> m b ( >> ) :: m a -> m b -> m b -- implementado por defecto: a >> b = a >>= \_ -> b return :: a -> m a -- = fallo puro :: String -> m a -- by-calls errorWithoutStackTrace por defectoEl método returnpuede resultar confuso para los programadores familiarizados con los lenguajes imperativos: no interrumpe el cálculo, sino que solo empaqueta un valor arbitrario del tipo aen una mónada m. El método failno tiene nada que ver con la naturaleza teórica de las mónadas, pero se usa en caso de un error de coincidencia de patrones dentro de una evaluación monádica. [2] ). El operador >>=es una función vinculante. El operador >> es un caso especial del operador >>=, que se usa cuando el resultado de la vinculación no es importante para nosotros.
Algunos tipos que implementan la clase Monad:
El lenguaje también tiene donotación -, que es una forma más conveniente de escribir funciones monádicas. En este ejemplo , f1usa la donotación -, pero se f2escribe usando operadores de enlace:
f1 = do s <- getLine putStrLn $ "Hola" ++ s putStrLn "Adiós" f2 = getLine >>= ( \ s -> putStrLn $ "Hola " ++ s ) >> putStrLn "Adiós"