¿Cómo diseñas programas en Haskell u otros lenguajes de programación funcionales?


52

Tengo cierta experiencia en lenguajes de programación orientados a objetos como C # o Ruby. Sé cómo diseñar un programa en estilo orientado a objetos, cómo crear clases y objetos, y cómo definir relaciones entre ellos. También conozco algunos patrones de diseño.

¿Cómo escriben las personas programas funcionales? ¿Cómo empiezan? ¿Existen patrones de diseño para lenguajes funcionales? ¿Se aplican metodologías como programación extrema o desarrollo ágil para lenguajes funcionales?


Respuestas:


24

Escribo mi respuesta principalmente con Haskell en mente, aunque muchos conceptos se aplican igualmente bien a otros lenguajes funcionales como Erlang, Lisp (s) y ML. Algunos incluso se aplican (hasta cierto punto) a Ruby, Python, Perl y Javascript.

¿Cómo escriben las personas programas funcionales? ¿Cómo empiezan?

Al escribir funciones. Cuando está haciendo programación funcional, está escribiendo maino está escribiendo una función auxiliar. A veces, su objetivo principal podría ser escribir un tipo de datos con varias funciones relevantes que operan en él.

La programación funcional es muy adecuada para los enfoques de arriba hacia abajo y de abajo hacia arriba. Haskell recomienda encarecidamente escribir sus programas en lenguaje de alto nivel y luego simplemente definir los detalles de su diseño de alto nivel. Ver minimum, por ejemplo:

minimum    :: (Ord a) => [a] -> a
minimum xs =  foldl1 min xs

La función para encontrar el elemento más pequeño en una lista se escribe simplemente como un recorrido sobre la lista, utilizando la función min para comparar cada elemento con el "acumulador" o valor mínimo actual.

¿Existen patrones de diseño para lenguajes funcionales?

Hay dos cosas que podrían equipararse a "patrones de diseño", en mi humilde opinión, funciones de orden superior y mónadas . Hablemos de lo primero. Las funciones de orden superior son funciones que toman otras funciones como entrada o producen funciones como salida. Cualquier lenguaje funcional en general, hace un uso intensivo de map, filteryfold(fold también se denomina "reducir"): tres funciones básicas de orden superior que aplican una función a una lista de diferentes maneras. Estos reemplazan la repetitiva para bucles de una manera hermosa. Pasar funciones como parámetros es una bendición extremadamente poderosa para la programación; muchos de los "patrones de diseño" pueden lograrse de manera más simple mediante el uso de funciones de orden superior, la posibilidad de crear las suyas propias y la capacidad de aprovechar la potente biblioteca estándar, que está llena de funciones útiles.

Las mónadas son el tema "más aterrador". Pero en realidad no dan tanto miedo. Mi forma favorita de pensar en las mónadas es pensar en ellas como envolviendo una función en una burbuja y dando superpoderes a esa función (que solo funcionan dentro de la burbuja). Podría dar más detalles, pero el mundo realmente no necesita otra analogía de mónada. Así que pasaré a ejemplos rápidos. Supongamos que quiero usar un "patrón de diseño" no determinista. Quiero ejecutar el mismo cálculo para varias entradas diferentes al mismo tiempo. No quiero elegir solo una entrada, quiero elegirlas todas. Esa sería la lista mónada:

allPlus2 :: [Int] -> [Int]
allPlus2 xs = do x <- xs
                 return (x + 2)

Ahora, la forma idiomática de realizar esto es en realidad map, pero por el bien de la ilustración, ¿pueden ver cómo la lista mónada me permitió escribir una función que parece funcionar en un valor, pero la dotó de la superpotencia para trabajar en cada elemento en ¿una lista? Otras superpotencias incluyen falla, estado, interacción con el "mundo exterior" y ejecución paralela. Estas superpotencias son muy potentes, y la mayoría de los lenguajes de programación permiten que las funciones con superpotencias se extiendan por todas partes. La mayoría de la gente dice que Haskell no permite estos superpoderes en absoluto, pero en realidad, Haskell solo los contiene en mónadas para que su efecto pueda ser limitado y observado.

tl; dr Grokking funciones de orden superior y mónadas es el equivalente de Haskell a patrones de diseño de grokking. Una vez que aprende estos conceptos de Haskell, comienza a pensar que los "patrones de diseño" son en su mayoría soluciones alternativas baratas para simular el poder de Haskell.

¿Se aplican metodologías como programación extrema o desarrollo ágil para lenguajes funcionales?

No veo nada que vincule estas estrategias de gestión a ningún paradigma de programación. Como dijo phynfo, la programación funcional prácticamente te obliga a realizar la descomposición de funciones, dividiendo un gran problema en subproblemas, por lo que los mini-hitos deberían ser pan comido. Existen herramientas como QuickCheck y Zeno para probar o incluso probar propiedades sobre las funciones que escribe.


"Podría dar más detalles, pero el mundo realmente no necesita otra analogía de mónada". - Siempre necesitamos más analogías para las mónadas y la tuya es una de las mejores que he visto.
Adam Gent

1
Gran respuesta, pero creo que su discusión sobre los patrones de diseño es un poco engañosa. Si bien no necesita patrones de diseño de estilo OO / GOF en Haskell, de hecho sería ridículo intentarlos, los patrones en sí mismos son simplemente formas en que una comunidad comunica soluciones a los tipos de problemas que surgen una y otra vez. La comunidad de Haskell todavía es muy joven, por lo que aún no hay muchos patrones de los que hablar, pero si me pidiera ejemplos de patrones de Haskell, mencionaría cosas como GADT o Arrowized FRP.
rtperson
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.