Una cosa que lo hace confuso es que las funciones "populares" como bind
y <*>
están orientadas a la praxis. Pero para entender los conceptos es más fácil mirar otras funciones primero. También vale la pena destacar que las mónadas se destacan porque están un poco sobrevaloradas en comparación con otros conceptos conectados.
Así que empezaré con los funtores en su lugar.
Los
Functors ofrecen una función (en notación Haskell) fmap :: (Functor f) => (a -> b) -> f a -> f b
. En otras palabras, tiene un contexto f
en el que puede elevar una función. Como puedes imaginar casi cualquier cosa es un funtor. Listas, Tal vez, Cualquiera de las funciones, E / S, tuplas, analizadores ... Cada una representa un contexto en el que puede aparecer un valor. Por lo tanto, puede escribir funciones extremadamente versátiles que funcionan en casi cualquier contexto utilizando fmap
o su variante en línea <$>
.
¿Qué otras cosas quieres hacer con los contextos? Es posible que desee combinar dos contextos. Por lo tanto, es posible que desee obtener una generalización de zip :: [a] -> [b] -> [(a,b)]
, por ejemplo, como este: pair :: (Monoidal f) => f a -> f b -> f (a,b)
.
Pero como es aún más útil en la práctica, las bibliotecas de Haskell ofrecen Applicative
, que es una combinación de Functor
y Monoidal
, y también de Unit
, que solo agrega que realmente puede poner valores "dentro" de su contexto con unit
.
Puedes escribir funciones extremadamente genéricas simplemente declarando estas tres cosas sobre el contexto en el que estás trabajando.
Monad
es solo otra cosa que puedes decir sobre eso. Lo que no mencioné antes es que ya tiene dos formas de combinar dos contextos: no solo puede pair
ellos, sino que también puede apilarlos, por ejemplo. Puedes tener una lista de listas. En el contexto de E / S, un ejemplo sería una acción de E / S que puede leer otras acciones de E / S de un archivo, por lo que tendría un tipo FilePath -> IO (IO a)
. ¿Cómo podemos deshacernos de ese apilamiento para obtener una función ejecutable IO a
? Ahí es donde entra Monad
s join
, nos permite combinar dos contextos apilados del mismo tipo. Lo mismo ocurre con los analizadores, tal vez etc. Y bind
es solo una forma más práctica de usar join
Por lo tanto, un contexto monádico solo tiene que ofrecer cuatro cosas y puede utilizarse con casi toda la maquinaria desarrollada para E / S, analizadores, fallos, etc.