mónada monadologia monadas leibniz las filosofía filosofia educatina doctrina haskell monads

haskell - monadologia - monadas filosofia



Función de unión de mónada (5)

De hecho, en cierto modo, join es donde realmente sucede toda la magia-- (>>=) se usa principalmente para su conveniencia.

Todas las clases de tipos basadas en Functor describen una estructura adicional utilizando algún tipo. Con Functor esta estructura adicional a menudo se la considera un "contenedor", mientras que con Monad tiende a considerarse como "efectos secundarios", pero esos son solo taquigrafías (a veces engañosas), es lo mismo de cualquier manera y no realmente cualquier cosa especial [0] .

La característica distintiva de Monad comparación con otras Functor es que puede integrar el flujo de control en la estructura adicional. La razón por la que puede hacer esto es que, a diferencia de fmap que aplica una función plana única sobre toda la estructura, (>>=) inspecciona elementos individuales y construye una nueva estructura a partir de eso.

Con un Functor plano, la construcción de una nueva estructura a partir de cada parte de la estructura original Functor al Functor , y cada capa representa un punto de flujo de control. Esto obviamente limita la utilidad, ya que el resultado es desordenado y tiene un tipo que refleja la estructura del control de flujo utilizado.

Los "efectos secundarios" monádicos son estructuras que tienen algunas propiedades adicionales [1] :

  • Dos efectos secundarios se pueden agrupar en uno (por ejemplo, "do X" y "do Y" se convierten en "do X, luego Y"), y el orden de agrupación no importa mientras se mantenga el orden de los efectos.
  • Existe un efecto secundario de "no hacer nada" (por ejemplo, "hacer X" y "no hacer nada" agrupados es lo mismo que "hacer X")

La función de join no es más que esa operación de agrupación: un tipo de mónada anidada como m (ma) describe dos efectos secundarios y el orden en que aparecen, y la join los agrupa en un solo efecto secundario.

Por lo tanto, en lo que respecta a los efectos secundarios monádicos, la operación de enlace es una abreviatura de "tomar un valor con efectos secundarios asociados y una función que introduce nuevos efectos secundarios, luego aplicar la función al valor mientras se combinan los efectos secundarios para cada uno" .

[0]: Excepto IO . IO es muy especial.

[1]: Si comparas estas propiedades con las reglas de una instancia de Monoid , verás un paralelismo cercano entre las dos. Esto no es una coincidencia, y de hecho es lo que "es solo un monoide en la categoría de endofunctores. ¿Cuál es el problema?" Se refiere a la línea.

Si bien las mónadas se representan en Haskell con las funciones de enlace y retorno, también pueden tener otra representación con la función de unión, como se explica aquí . Sé que el tipo de esta función es M (M (X)) -> M (X), pero ¿qué hace esto en realidad?


Desde la misma página recuperamos esta información join x = x >>= id , con el conocimiento de cómo funcionan las funciones de bind e id , debería ser capaz de averiguar qué hace la join .


Lo que hace la unión ha sido adecuadamente descrito por las otras respuestas hasta ahora, creo. Si está buscando una comprensión más intuitiva ... si se está preguntando qué significa "unión" ... entonces, desafortunadamente, la respuesta variará dependiendo de la mónada en cuestión, específicamente de lo que significa M (X) " "y lo que M (M (X))" significa ".

Si M es la mónada de la Lista, entonces M (M (X)) es una lista de listas, y unirse significa "aplanar". Si M es la mónada Maybe, entonces un elemento de M (M (X)) podría ser "Just (Just x)", "Just Nothing", o "Nothing", y unirse significa colapsar esas estructuras de forma lógica para "Solo x", "Nada" y "Nada" respectivamente (similar a la respuesta de camccann de combinar como efectos secundarios).

Para las mónadas más complicadas, M (M (X)) se convierte en algo muy abstracto y decidir qué M (M (X)) y unir "media" se vuelve más complicado. En todos los casos es algo así como el caso de la mónada de la Lista, en el que colapsas dos capas de abstracción de la Mónada en una capa, pero el significado va a variar. Para la mónada Estatal, la respuesta de camccann de combinar dos efectos secundarios es: unir significa esencialmente combinar dos transiciones de estado sucesivas. La mónada de Continuación es especialmente innovadora, pero la combinación matemática en realidad es bastante clara aquí: M (X) corresponde al "doble espacio doble" de X, lo que los matemáticos podrían escribir como X** (continuaciones en sí mismas, es decir, mapas de X- > R donde R es un conjunto de resultados finales, corresponde al único espacio dual X* ), y la combinación corresponde a un mapa extremadamente natural de X**** a X** . El hecho de que las mónadas de Continuación cumplan con las leyes de la mónada corresponde al hecho matemático de que generalmente no tiene mucho sentido aplicar el operador de espacio dual * más de dos veces.

Pero yo divago.

Personalmente trato de resistir la tentación de aplicar una analogía única a todos los tipos posibles de mónadas; las mónadas son un concepto demasiado general para ser encasillado por una única analogía descriptiva. Lo que significa unirse va a variar según la analogía con la que estés trabajando en un momento dado.


Lo que hace, conceptualmente, se puede determinar con solo mirar el tipo: desenvuelve o aplana el contenedor / cálculo monádico exterior y devuelve el (los) valor (es) monádico (s) producido (s) en el mismo.

La forma en que lo hace realmente está determinada por el tipo de mónada con la que está tratando. Por ejemplo, para la mónada de la Lista, ''unirse'' es equivalente a concat .


Los mapas de la operación de enlace: ma -> (a -> mb) -> mb . En ma y (la primera) mb , tenemos dos m s. Para mi intuición, la comprensión de las operaciones vinculantes y monádicas ha llegado a mentir, en gran medida, en la comprensión de cómo y de qué manera se combinarán esos dos m s (instancias del contexto monádico). Me gusta pensar en la mónada del escritor como un ejemplo para comprender la join . Writer se puede utilizar para registrar operaciones. ma tiene un log en ella (a -> mb) producirá otro registro en ese primer mb . El segundo mb combina ambos registros.

(Y un mal ejemplo es pensar en la mónada Tal vez, porque Just + Just = Just and Nothing + anything = Nothing (o F # Some and None ) son tan poco informativos que se pasa por alto el hecho de que algo importante está sucediendo. pensar simplemente como una única condición para proceder y Nothing como simplemente una sola bandera para detener. Como señales en el camino, dejadas atrás a medida que avanza el cálculo (lo que es una impresión razonable, ya que parece que no se ha creado el Just o Nothing final. arañe el último paso de la computación sin que se transfiera nada de los anteriores. Cuando realmente necesite enfocarse en la combinatoria de Just sy Nothing s en cada ocasión.)

El tema se cristalizó para mí al leer el artículo de Miran Lipovaca, ¡Aprendan un haskell para el bien !, Capítulo 12, la última sección sobre las leyes de la mónada. http://learnyouahaskell.com/a-fistful-of-monads#monad-laws , Associativity. Este requisito es: "Hacer (ma >>= f) >>= g es como hacer ma >>= (/x -> fx >>= g) [uso ma para m ]". Bueno, en ambos lados el argumento pasa primero a f luego a g . Entonces, ¿qué quiere decir con "no es fácil ver cómo esos dos son iguales"? ¡No es fácil ver cómo pueden ser diferentes!

La diferencia está en la asociatividad de las uniones de m s (contextos), lo que hacen los enlaces, junto con el mapeo. La vinculación se desenrolla o gira alrededor de la m para llegar a la a la que se aplica f , pero eso no es todo. La primera m (en ma ) se mantiene mientras que f genera una segunda m (en mb ). Luego bind combina-- join s - ambos m s. La clave para bind está tanto en la join como en el desenvolvimiento ( map ). Y creo que la confusión sobre la join es indicativa de fijarse en el aspecto de desenvolvimiento de bind obtener la a out of ma para coincidir con la firma del argumento de f - y pasar por alto el hecho de que los dos m s (de ma y entonces mb ) hay que reconciliarse. (Descartar la primera m puede ser la forma adecuada de manejarlo en algunos casos (quizás), pero eso no es cierto en general, como lo ilustra Writer).

A la izquierda, unimos ma a f primero, luego a g segundo. Así que el registro será como: ("before f" + "after f") + "after g" . A la derecha, mientras que las funciones f y g se aplican en el mismo orden, ahora enlazamos primero con g . Así que el registro será como: "before f" + ("after f" + "after g") . Los parens no están en la (s) cadena (s), por lo que el registro es el mismo en ambos sentidos y se cumple la ley. (Considerando que si el segundo registro hubiera salido como "after f" + "after g" + "before f" - ¡entonces estaríamos en problemas matemáticos!).

Si bind fmap bind como fmap más join para Writer, obtenemos fmap f ma , donde f:a -> mb , lo que da como resultado m(mb) . Piense en la primera m en ma como "antes de f". La f se aplica a la a dentro de esa primera m ahora llega una segunda m (o mb ), dentro de la primera m , donde se realiza el mapeo f . Piense en la segunda m en mb como "después de f". m(mb) = ("antes de f" ("después de f" b )). Ahora usamos Unir para colapsar los dos registros, el m s, haciendo un nuevo m . Escritor utiliza un monoide y concatenamos. Otras mónadas combinan contextos de otras maneras, obedeciendo las leyes. Que tal vez sea la parte principal de entenderlos.