Se habla mucho de mónadas en estos días. He leído algunos artículos / publicaciones de blog, pero no puedo ir lo suficientemente lejos con sus ejemplos para comprender completamente el concepto. La razón es que las mónadas son un concepto de lenguaje funcional y, por lo tanto, los ejemplos están en idiomas con los que no he trabajado (ya que no he usado un lenguaje funcional en profundidad). No puedo comprender la sintaxis lo suficientemente profundo como para seguir los artículos por completo ... pero puedo decir que hay algo que vale la pena entender allí.
Sin embargo, conozco C # bastante bien, incluidas las expresiones lambda y otras características funcionales. Sé que C # solo tiene un subconjunto de características funcionales, por lo que tal vez las mónadas no se puedan expresar en C #.
Sin embargo, ¿seguramente es posible transmitir el concepto? Por lo menos eso espero. Tal vez pueda presentar un ejemplo de C # como base y luego describir lo que un desarrollador de C # desearía poder hacer desde allí, pero no puede porque el lenguaje carece de funciones de programación funcionales. Esto sería fantástico, ya que transmitiría la intención y los beneficios de las mónadas. Así que aquí está mi pregunta: ¿Cuál es la mejor explicación que puede dar de mónadas a un desarrollador C # 3?
¡Gracias!
(EDITAR: Por cierto, sé que ya hay al menos 3 preguntas de "qué es una mónada" en SO. Sin embargo, me enfrento al mismo problema con ellas ... por lo que esta pregunta es necesaria en mi opinión, debido al desarrollador de C # enfoque. Gracias.)
Respuestas:
La mayor parte de lo que hace en la programación durante todo el día es combinar algunas funciones para crear funciones más grandes a partir de ellas. Por lo general, no solo tiene funciones en su caja de herramientas, sino también otras cosas como operadores, asignaciones de variables y similares, pero en general su programa combina muchos "cálculos" con cálculos más grandes que se combinarán aún más.
Una mónada es alguna forma de hacer esta "combinación de cálculos".
Por lo general, su "operador" más básico para combinar dos cálculos es
;
:Cuando dices esto quieres decir "primero haz
a
, luego hazb
". El resultadoa; b
es básicamente una vez más un cálculo que se puede combinar junto con más cosas. Esta es una mónada simple, es una forma de combinar pequeños cálculos con los más grandes. El;
dice "haz lo de la izquierda, luego haz lo de la derecha".Otra cosa que puede verse como una mónada en lenguajes orientados a objetos es el
.
. A menudo encuentras cosas como esta:Los
.
básicamente significa "evalúan el cálculo de la izquierda, y luego llamar al método a la derecha en el resultado de eso". Es otra forma de combinar funciones / cálculos, un poco más complicado que;
. Y el concepto de encadenar cosas.
es una mónada, ya que es una forma de combinar dos cálculos en un nuevo cálculo.Otra mónada bastante común, que no tiene una sintaxis especial, es este patrón:
Un valor de retorno de -1 indica falla, pero no hay una forma real de abstraer esta comprobación de errores, incluso si tiene muchas llamadas API que necesita combinar de esta manera. Básicamente, esta es otra mónada que combina las llamadas de función por la regla "si la función de la izquierda devolvió -1, devuelve -1 nosotros mismos, de lo contrario, llame a la función de la derecha". Si tuviéramos un operador
>>=
que hiciera esto, simplemente podríamos escribir:Haría las cosas más legibles y ayudaría a resumir nuestra forma especial de combinar funciones, de modo que no necesitemos repetirnos una y otra vez.
Y hay muchas más formas de combinar funciones / cálculos que son útiles como un patrón general y que pueden resumirse en una mónada, lo que permite al usuario de la mónada escribir código mucho más conciso y claro, ya que toda la contabilidad y administración de Las funciones utilizadas se realizan en la mónada.
Por ejemplo, lo anterior
>>=
podría extenderse para "hacer la verificación de errores y luego llamar al lado derecho en el socket que obtuvimos como entrada", de modo que no necesitemos especificar explícitamentesocket
muchas veces:La definición formal es un poco más complicada ya que debe preocuparse por cómo obtener el resultado de una función como entrada a la siguiente, si esa función necesita esa entrada y ya que desea asegurarse de que las funciones que combina encajan la forma en que intentas combinarlos en tu mónada. Pero el concepto básico es que formaliza diferentes formas de combinar funciones.
fuente
;
ejemplo: ¿Qué objetos / tipos de datos asigna;
? (Piense enList
mapasT
paraList<T>
) ¿Cómo funciona el;
mapa de morfismos / funciones entre objetos / tipos de datos? Lo que espure
,join
,bind
para;
?Ha pasado un año desde que publiqué esta pregunta. Después de publicarlo, profundicé en Haskell durante un par de meses. Lo disfruté muchísimo, pero lo dejé a un lado justo cuando estaba listo para profundizar en las mónadas. Regresé al trabajo y me concentré en las tecnologías que requería mi proyecto.
Y anoche, vine y releí estas respuestas. Lo que es más importante , releí el ejemplo específico de C # en los comentarios de texto del video de Brian Beckman que alguien menciona arriba . Fue tan claro e iluminador que decidí publicarlo directamente aquí.
Debido a este comentario, no solo siento que entiendo exactamente qué son las mónadas ... me doy cuenta de que en realidad escribí algunas cosas en C # que son mónadas ... o al menos muy cercanas, y me esfuerzo por resolver los mismos problemas.
Entonces, aquí está el comentario: esta es una cita directa del comentario aquí por sylvan :
fuente
Una mónada es esencialmente procesamiento diferido. Si está intentando escribir código que tiene efectos secundarios (p. Ej., E / S) en un idioma que no los permite y solo permite la computación pura, una elusión es decir: "Ok, sé que no hará efectos secundarios para mí, pero ¿puedes calcular qué pasaría si lo hicieras? "
Es una especie de trampa.
Ahora, esa explicación te ayudará a comprender la intención general de las mónadas, pero el diablo está en los detalles. ¿Cómo funciona exactamente qué a calcular las consecuencias? A veces no es bonito.
La mejor manera de dar una visión general de cómo para alguien acostumbrado a la programación imperativa es decir que lo coloca en un DSL en el que las operaciones que se parecen sintácticamente a lo que está acostumbrado fuera de la mónada se utilizan en su lugar para construir una función que sirva lo que desea si pudiera (por ejemplo) escribir en un archivo de salida. Casi (pero no realmente) como si estuviera construyendo código en una cadena para luego ser evaluado.
fuente
Maybe
yEither e
) y la administración de estado (State s
,ST s
) me parecen instancias particulares de "Por favor calcule qué sucedería si lo hiciera [efectos secundarios para mí]". Otro ejemplo sería el no determinismo ([]
).Estoy seguro de que otros usuarios publicarán en profundidad, pero encontré este video útil hasta cierto punto, pero diré que todavía no estoy al punto de fluidez con el concepto de tal manera que podría (o debería) comenzar a resolver problemas intuitivamente con las mónadas.
fuente
Puedes pensar en una mónada como un C #
interface
que las clases tienen que implementar . Esta es una respuesta pragmática que ignora toda la categoría de matemática teórica detrás de por qué querría elegir tener estas declaraciones en su interfaz e ignora todas las razones por las que desea tener mónadas en un lenguaje que intenta evitar efectos secundarios, pero me pareció un buen comienzo como alguien que entiende las interfaces (C #).fuente
Vea mi respuesta a "¿Qué es una mónada?"
Comienza con un ejemplo motivador, funciona a través del ejemplo, deriva un ejemplo de una mónada y define formalmente "mónada".
No asume ningún conocimiento de programación funcional y utiliza pseudocódigo con
function(argument) := expression
sintaxis con las expresiones más simples posibles.Este programa C # es una implementación del pseudocódigo mónada. (Como referencia:
M
es el constructor de tipos,feed
es la operación "vincular" ywrap
es la operación "regresar").fuente