language-agnostic haskell functional-programming monads arrows

language agnostic - Mónadas vs. Flechas



language-agnostic haskell (2)

Hay dos excelentes trabajos de Lindley, Wadler y Yallop (discutidos en LTU here ).

Lo más importante para entender es que hay más cosas que son flechas que cosas que son mónadas. Por el contrario, las mónadas son estrictamente más poderosas que las flechas (el segundo documento anterior especifica con precisión de qué manera).

En particular, las mónadas son flechas equipadas con una función de aplicar de tipo (a ~> b, a) ~> b , donde (~>) es el constructor para una flecha dada. Lindley et al. señale que esto destruye la distinción meticulosa que mantienen las flechas entre los términos y los comandos (o, si lo prefiere, los objetos y los morfismos).

Los funtores aplicativos tienen una amplia variedad de aplicaciones, particularmente para las cosas que mejor se consideran operaciones en transmisiones. De hecho, se puede pensar que las flechas surgen de la generalización de la noción de un transformador en las corrientes (es decir, la introducción de un nuevo lenguaje para morfismos en los objetos construidos por un funcionador aplicativo dado).

En mi experiencia, debido a que las mónadas difuminan la distinción entre objetos y morfismos (es decir, si estoy usando las palabras correctamente, da lugar a una categoría cartesiana cerrada), entonces un término en una mónada es generalmente mucho más necesariamente opaco que un término en una flecha o un funtor aplicativo (aunque tenga en cuenta que ambos le permiten inyectar funciones arbitrarias mediante los métodos arr y pure , respectivamente).

Entonces, si algo no tiene las características de una mónada (aunque conceptualmente forma uno), entonces está potencialmente abierto a una mayor inspección y optimización. También es potencialmente más fácil de serializar. De ahí el uso de aplicativos y flechas en analizadores sintácticos y modelado de circuitos.

Lo anterior intentó ser general y descriptivo. A continuación se encuentran algunas de mis reglas generales.

Si necesita modelar algo que se parece al estado, comience con una mónada. Si necesita modelar algo que se parece al flujo de control global (es decir, excepciones, continuaciones), comience con una mónada. Si surge un requisito que entra en conflicto con el poder y la generalidad de las mónadas (es decir, para las cuales join (join :: m (ma) -> ma) es demasiado poderoso), considera eliminar el poder de lo que estás usando.

Si necesita modelar flujos y transformaciones en transmisiones, y particularmente las secuencias para las cuales ciertas características (particularmente vistas ilimitadas del pasado y futuro) deberían ser opacas, entonces comience con un funtor aplicativo. Si necesita un razonamiento más sólido sobre las propiedades de las transformaciones en las transmisiones, piense en buscar una flecha.

O, muy crudamente, los aplicativos son para las acciones de los circuitos, las flechas son para las estructuras de los circuitos, y las mónadas son para efectos computacionales de propósito general.

Por supuesto, hay mucho más en la historia. Para los solicitantes, vea el trabajo de Conal Elliott sobre FRP en particular. Para las flechas, consulte la biblioteca del analizador HXT XML , el proyecto Yampa FRP , el marco web Haskell on a Horse , el clásico documento de Hudak y Liu "Tapar un fuga de espacio con una flecha" , entre otras cosas. Para las mónadas, mira en todas partes. Y, por supuesto, tenga en cuenta que solo porque algo sea una mónada, eso no significa que la notación aplicativa no sea más clara y expresiva.

Estoy ampliamente familiarizado con los conceptos de monads y arrows que se usan en la programación funcional. También entiendo que se pueden usar para resolver problemas similares.

Sin embargo, todavía estoy un poco confundido acerca de cómo seleccionar cuál usar en cualquier situación dada.

¿Cuándo debería usar mónadas y cuándo debería usar flechas?


La respuesta corta es que las Flechas son más generales que las Mónadas y también son más difíciles de usar. Por lo tanto, debes usar Mónadas siempre que puedas, dejando el uso de Flechas para los casos en que las Mónadas no sean aplicables.

La respuesta de "ruta escénica" sigue.

John Hughes, la persona que introdujo Arrows, ha publicado dos excelentes trabajos que recomiendo: "Generalización de mónadas a flechas" y "Programación con flechas" . Estos dos artículos son fáciles de leer y brindan la respuesta a su pregunta. Incluso si algunas personas no entienden todos los detalles o el código en estos dos artículos, seguramente encontrarán mucha información y explicaciones muy útiles sobre Mónadas y Flechas.

Ahora resaltaré los puntos principales de estos artículos que pertenecen a su pregunta

Cuando se introdujeron las Mónadas, la gente pensó que eran todopoderosas. De hecho, las Mónadas tienen mucha potencia. Pero en algún momento, se descubrió que hay casos donde las mónadas no se pueden aplicar. Estos casos tienen que ver con entradas múltiples, especialmente cuando algunas de las entradas son estáticas y algunas de las entradas son dinámicas. Entonces, John Hughes dio un paso adelante e introdujo Arrows.

Las flechas son más generales que las Mónadas. Las flechas son un superconjunto de Mónadas. Pueden hacer todo lo que las Mónadas hacen y más. Pero también son más difíciles de usar. John Hughes recomienda que uses Mónadas siempre que puedas y que deberías usar las Flechas cuando no puedas usar Mónadas.

Estoy de acuerdo con John Hughes. También me recuerda la cita de Einstein "Todo debe hacerse lo más simple posible, pero no más simple".

Por supuesto, todo depende de la situación particular en cuestión. Dejame explicar. Supongamos que estás aprendiendo Haskell. Entonces sería una gran tarea hacer cada programa usando un enfoque monádico y rehacerlo usando un enfoque basado en flechas. Cuando aprenda, debe esforzarse por explorar todas las posibilidades e implementar todo tipo de enfoques. De esta forma, obtienes una gran visión y puedes comparar diferentes soluciones de primera mano.

Ahora supongamos que desea proporcionar una biblioteca a la comunidad. Bueno, le debes a la gente que leerá tu código que deberías usar el enfoque que es más fácil de entender y aún así hace el trabajo. También le debe a las personas que usarán su código que su solución carece de complejidad innecesaria. De esta forma, su solución es más fácil de mantener y menos propensa a errores e insectos.

Pero, ¿y si estás en un caso límite? Supongamos que no estás seguro de si necesitarás o no el poder extra de Arrows. Entonces ¿qué deberías hacer? ¿Deberías comenzar con un enfoque monádico y luego cambiar a uno basado en flechas si surge la necesidad? ¿O debería comenzar con Arrows desde el principio, evitando un cambio costoso a mitad del proyecto?

Una vez más, mi respuesta es intentar el primer acercamiento: intente usar Mónadas si puede. Si más tarde descubre que no puede usar Mónadas, tendrá que soportar un cambio costoso, donde tendrá que reiniciar y rehacer el proyecto para poder usar las Flechas. Este enfoque requerirá más tiempo y otros recursos de su parte. Pero sabrá que hizo lo correcto, que era tratar de proporcionar la solución más simple, clara y menos compleja posible.

Evitar la complejidad innecesaria es lo más importante. Créanlo o no, esta es la razón por la cual los conceptos (como la composición de funciones, Mónadas y Flechas) de la Teoría de Categoría se introdujeron en la Informática. ¿Irónico?