He leído muchas publicaciones que explican qué son las mónadas, cómo unit
y cómo bind
funcionan, algunas de ellas sumergiéndose directamente en la teoría de categorías tan abstracta (al menos para mí) que hace que los ojos sangren, algunas ignorando eso por completo y tocando analogías extrañas de burritos, cajas y que no.
Después de algunas semanas de estudio y muchas neuronas fritas, (creo) entiendo cómo funcionan las mónadas. Pero todavía hay una cosa que se me escapa, algo que pocas publicaciones realmente tocan (a excepción de IO y estado):
¿POR QUÉ?
¿Por qué importan las mónadas? ¿Por qué son tan importantes? ¿Qué problemas están resolviendo? ¿Esos problemas solo se pueden resolver con Mónadas o hay alguna otra forma?
functional-programming
problem-solving
monad
Dummy Me
fuente
fuente
Respuestas:
No necesitas mónadas para resolver nada. Simplemente hacen que ciertas cosas sean más simples. Mucha gente se vuelve demasiado abstracta y teórica al explicar las mónadas. En su mayoría, las mónadas son un patrón que aparece una y otra vez en la programación. Al reconocer ese patrón, podemos simplificar nuestro código y evitar volver a implementar ciertas funciones.
Para Haskell, desde un punto de vista concreto, lo más visible que permiten las mónadas es hacer notación . Las comprensiones de listas en Haskell y otros idiomas también aprovechan mucho las mónadas. También puede crear bibliotecas como Control.Monad .
Todos estos proporcionan simplificaciones útiles, y una vez que lo ha implementado para una mónada, lo obtiene automáticamente para todas las mónadas. Esta es una de las principales razones por las que la reutilización de código es mucho más fácil para la programación funcional que otros paradigmas.
fuente
IO
es la mónada más prominente de Haskell , pero no estaba enumerando ejemplos de mónadas individuales. Estaba enumerando ejemplos de las abstracciones generales que permiten. Estaba tratando de entender por qué, por ejemplo, el primer tipo en pensar en usar una mónada para IO pensaría que es una buena idea en general.Es más fácil de entender si observa las mónadas particulares y ve qué problemas resuelven. Por ejemplo, en Haskell:
IO: permite que IO se represente en el sistema de tipos, por lo que puede separar claramente las funciones puras de las funciones que realizan IO.
Lista: le permite hacer comprensiones de listas y cálculos terminológicos de nodo.
Quizás: una mejor alternativa a los valores nulos y que respalde algo comparable al operador de fusión nula de C #.
Parsec: un conveniente DSL para escribir analizadores.
Por lo tanto, es fácil (espero) ver la justificación de las mónadas individuales, ya que todas son bastante útiles. Pero los problemas que resuelven también son bastante diferentes y, a primera vista, no parecen tener mucho en común, excepto que todos están relacionados con alguna lógica para encadenar operaciones. Las mónadas son útiles porque le permiten construir una variedad de herramientas.
¿Podrían implementarse los ejemplos anteriores sin mónadas? Ciertamente, podrían implementarse de manera ad-hoc, pero tener mónadas integradas en el lenguaje permite el soporte directo del lenguaje como la
do
notación que funciona con todas las mónadas.fuente
Una cosa que lo hace confuso es que las funciones "populares" les gusta
bind
y<*>
están orientadas a la praxis. Pero para comprender los conceptos es más fácil observar otras funciones primero. También vale la pena señalar que las mónadas se destacan porque están un poco sobrevaloradas en comparación con otros conceptos conectados. Así que comenzaré con functors en su lugar.Los functores ofrecen una función (en notación Haskell)
fmap :: (Functor f) => (a -> b) -> f a -> f b
. En otras palabras, tiene un contexto en elf
que puede levantar una función. Como puedes imaginar, casi cualquier cosa es un functor. Listas, Quizás, Cualquiera, funciones, E / S, tuplas, analizadores ... Cada uno 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 utilizandofmap
o su variante en línea<$>
.¿Qué otras cosas quieres hacer con los contextos? Es posible que desee combinar dos contextos. Así que es posible que desee obtener una generalización de
zip :: [a] -> [b] -> [(a,b)]
, por ejemplo, así:pair :: (Monoidal f) => f a -> f b -> f (a,b)
.Pero debido a que es aún más útil en la práctica, las bibliotecas de Haskell en su lugar ofrecen
Applicative
, que es una combinación deFunctor
yMonoidal
, y también deUnit
, que simplemente agrega que realmente puede poner valores "dentro" de su contextounit
.Puede escribir funciones extremadamente genéricas simplemente indicando estas tres cosas sobre el contexto en el que está 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 combinarlospair
, sino que también puede apilarlos, por ejemplo, puede 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 tipoFilePath -> IO (IO a)
. ¿Cómo podemos deshacernos de ese apilamiento para obtener una función ejecutableIO a
? Ahí es donde entraMonad
sjoin
, nos permite combinar dos contextos apilados del mismo tipo. Lo mismo ocurre con los analizadores sintácticos, Quizás, etc. Ybind
es solo una forma más práctica de usarjoin
Entonces, un contexto monádico solo tiene que ofrecer cuatro cosas y puede usarse con casi toda la maquinaria desarrollada para E / S, para analizadores, para fallas, etc.
fuente
Monads le permite expresar varios cálculos no puros, así como simplificar el código
Y, lo que es más importante, sin comprometer las construcciones de lenguaje puro y obtener un lenguaje más limpio.
fuente
Maybe
no están relacionadas con nada externo.