simbolos peta pattern para opciones lenguajes hacer funcionales español entornos ejemplos desarrollo como haskell functional-programming

peta - pattern matching haskell



¿Cuál es el alboroto sobre Haskell? (17)

Encuentro que para ciertas tareas soy increíblemente productivo con Haskell.

La razón es debido a la sintaxis sucinta y la facilidad de las pruebas.

Así es como es la sintaxis de declaración de función:

foo a = a + 5

Esa es la manera más simple que se me ocurre de definir una función.

Si escribo el inverso

inverseFoo a = a - 5

Puedo verificar que sea inversa a cualquier entrada aleatoria escribiendo

prop_IsInverse :: Double -> Bool
prop_IsInverse a = a == (inversoFoo $ foo a)

Y llamando desde la línea de comando

jonny @ ubuntu: runhaskell quickCheck + nombres fooFileName.hs

Lo cual verificará que todas las propiedades en mi archivo se mantengan, al probar aleatoriamente las entradas cien veces más.

No creo que Haskell sea el lenguaje perfecto para todo, pero cuando se trata de escribir pequeñas funciones y pruebas, no he visto nada mejor. Si su programación tiene un componente matemático, esto es muy importante.

Conozco a unos pocos programadores que siguen hablando de Haskell cuando están entre ellos, y aquí en SO, parece que a todos les encanta ese lenguaje. Ser bueno en Haskell parece algo así como el sello distintivo de un genio programador.

¿Alguien puede dar algunos ejemplos de Haskell que muestren por qué es tan elegante / superior?


Estás haciendo una pregunta incorrecta.

Haskell no es un lenguaje en el que vean algunos ejemplos geniales y digan "aha, ahora lo veo, eso es lo que lo hace bueno".

Es más, tenemos todos estos otros lenguajes de programación, y todos son más o menos similares, y luego está Haskell, que es totalmente diferente y loco de una manera que es totalmente increíble una vez que te acostumbras a la locura. Pero el problema es que lleva bastante tiempo aclimatarse a la locura. Cosas que distinguen a Haskell de casi cualquier otro lenguaje incluso semi-general:

  • Evaluación diferida
  • Sin efectos secundarios (todo es puro, IO / etc. ocurre a través de mónadas)
  • Sistema de tipo estático increíblemente expresivo

así como algunos otros aspectos que son diferentes de muchos lenguajes convencionales (pero compartidos por algunos):

  • funcional
  • espacio en blanco significativo
  • tipo inferido

Como algunos otros carteles han respondido, la combinación de todas estas características significa que piensas en la programación de una manera completamente diferente. Por lo tanto, es difícil encontrar un ejemplo (o un conjunto de ejemplos) que comunique esto adecuadamente a Joe-mainstream-programador. Es una experiencia. (Para hacer una analogía, puedo mostrarte fotos de mi viaje a China en 1970, pero después de ver las fotos, todavía no sabrás cómo fue vivir allí durante ese tiempo. De manera similar, puedo mostrarte un Haskell ''quicksort'', pero aún no sabrá lo que significa ser un Haskeller.)


Este es el ejemplo que me convenció para aprender Haskell (y amiguito, estoy contento de haberlo hecho).

-- program to copy a file -- import System.Environment main = do --read command-line arguments [file1, file2] <- getArgs --copy file contents str <- readFile file1 writeFile file2 str

OK, es un programa corto y legible. En ese sentido, es mejor que un programa C. Pero, ¿cómo es esto tan diferente de (digamos) un programa de Python con una estructura muy similar?

La respuesta es una evaluación perezosa. En la mayoría de los lenguajes (incluso algunos funcionales), un programa estructurado como el anterior daría lugar a que todo el archivo se cargue en la memoria y luego se escriba de nuevo con un nuevo nombre.

Haskell es "flojo". No calcula las cosas hasta que sea necesario, y por extensión no calcula las cosas que nunca necesita. Por ejemplo, si eliminara la línea writeFile , Haskell no se molestaría en leer nada del archivo en primer lugar.

Tal como está, Haskell se da cuenta de que writeFile depende de readFile y, por lo tanto, puede optimizar esta ruta de datos.

Si bien los resultados dependen del compilador, lo que sucederá normalmente cuando ejecute el programa anterior es este: el programa lee un bloque (digamos 8 KB) del primer archivo, luego lo escribe en el segundo archivo y luego lee otro bloque del primero archivo, y lo escribe en el segundo archivo, y así sucesivamente. (¡Prueba correr strace !)

... que se parece mucho a lo que haría la implementación eficiente de C de una copia de archivo.

Entonces, Haskell le permite escribir programas compactos y legibles, a menudo sin sacrificar mucho rendimiento.

Otra cosa que debo agregar es que Haskell simplemente hace que sea difícil escribir programas defectuosos. El sorprendente sistema de tipos, la falta de efectos secundarios y, por supuesto, la compacidad del código Haskell reduce los errores por al menos tres razones:

  1. Mejor diseño de programa La complejidad reducida conduce a menos errores de lógica.

  2. Código compacto. Menos líneas para que los errores existan.

  3. Compilar errores Muchos de los errores no son válidos Haskell .

Haskell no es para todos. Pero todos deberían intentarlo.


Estoy de acuerdo con aquellos que dijeron que la programación funcional hace que tu cerebro vea la programación desde un ángulo diferente. Solo lo he usado como aficionado, pero creo que cambió fundamentalmente la forma en que abordo un problema. No creo que hubiera sido tan efectivo con LINQ sin haber estado expuesto a Haskell (y el uso de generadores y listas de comprensión en Python).


Estoy de acuerdo con otros en que ver algunos pequeños ejemplos no es la mejor manera de presumir a Haskell. Pero daré algunos de todos modos. Aquí hay una solución rápida para los problemas del Proyecto Euler 18 y 67 , que le piden que busque la ruta de suma máxima desde la base hasta el ápice de un triángulo:

bottomUp :: (Ord a, Num a) => [[a]] -> a bottomUp = head . bu where bu [bottom] = bottom bu (row : base) = merge row $ bu base merge [] [_] = [] merge (x:xs) (y1:y2:ys) = x + max y1 y2 : merge xs (y2:ys)

Aquí hay una implementación completa y reutilizable del algoritmo BubbleSearch de Lesh y Mitzenmacher. Lo usé para empacar archivos de medios grandes para el almacenamiento de archivos en DVD sin desperdicio:

data BubbleResult i o = BubbleResult { bestResult :: o , result :: o , leftoverRandoms :: [Double] } bubbleSearch :: (Ord result) => ([a] -> result) -> -- greedy search algorithm Double -> -- probability [a] -> -- list of items to be searched [Double] -> -- list of random numbers [BubbleResult a result] -- monotone list of results bubbleSearch search p startOrder rs = bubble startOrder rs where bubble order rs = BubbleResult answer answer rs : walk tries where answer = search order tries = perturbations p order rs walk ((order, rs) : rest) = if result > answer then bubble order rs else BubbleResult answer result rs : walk rest where result = search order perturbations :: Double -> [a] -> [Double] -> [([a], [Double])] perturbations p xs rs = xr'' : perturbations p xs (snd xr'') where xr'' = perturb xs rs perturb :: [a] -> [Double] -> ([a], [Double]) perturb xs rs = shift_all p [] xs rs shift_all p new'' [] rs = (reverse new'', rs) shift_all p new'' old rs = shift_one new'' old rs (shift_all p) where shift_one :: [a] -> [a] -> [Double] -> ([a]->[a]->[Double]->b) -> b shift_one new'' xs rs k = shift new'' [] xs rs where shift new'' prev'' [x] rs = k (x:new'') (reverse prev'') rs shift new'' prev'' (x:xs) (r:rs) | r <= p = k (x:new'') (prev'' `revApp` xs) rs | otherwise = shift new'' (x:prev'') xs rs revApp xs ys = foldl (flip (:)) ys xs

Estoy seguro de que este código parece un galimatías aleatorio. Pero si lees BubbleSearch y entiendes el algoritmo, te sorprenderá que sea posible empaquetar el algoritmo en código sin decir nada sobre lo que estás buscando.

Después de darle algunos ejemplos como me pidió, diré que la mejor manera de comenzar a apreciar a Haskell es leer el documento que me dio las ideas que necesitaba para escribir el empaquetador de DVD: Por qué la Programación Funcional Importa por John Hughes. El documento realmente es anterior a Haskell, pero explica brillantemente algunas de las ideas que hacen que las personas como Haskell.


La forma en que me fue planteada, y lo que creo que es cierto después de haber trabajado en Haskell durante un mes, es el hecho de que la programación funcional tuerce el cerebro de maneras interesantes: te obliga a pensar en problemas familiares de diferentes maneras. : en lugar de bucles, piense en mapas, pliegues y filtros, etc. En general, si tiene más de una perspectiva sobre un problema, lo habilita mejor para razonar sobre este problema y cambiar puntos de vista según sea necesario.

La otra cosa realmente buena acerca de Haskell es su sistema de tipos. Está estrictamente tipado, pero el motor de inferencia tipo hace que se sienta como un programa de Python que te dice mágicamente cuándo has cometido un error estúpido relacionado con el tipo. Los mensajes de error de Haskell a este respecto son algo inexistentes, pero a medida que se familiarice con el idioma, se dirá a sí mismo: ¡esto es lo que se supone que debe ser el tipeo!


Lo que realmente distingue a Haskell es el esfuerzo que se hace en su diseño para hacer cumplir la programación funcional. Puede programar en un estilo funcional en casi cualquier idioma, pero es muy fácil abandonarlo a la primera conveniencia. Haskell no le permite abandonar la programación funcional, por lo que debe llevarlo a su conclusión lógica, que es un programa final que es más fácil de razonar, y evita una clase completa de los tipos más espinosos de errores.

Cuando se trata de escribir un programa para su uso en el mundo real, es posible que a Haskell le falte algo práctico, pero su solución final será mejor por haber conocido a Haskell desde el principio. Definitivamente todavía no estoy allí, pero hasta ahora el aprendizaje de Haskell ha sido mucho más esclarecedor que, digamos, que Lisp estaba en la universidad.


No podría darte un ejemplo, soy un chico de OCaml, pero cuando estoy en una situación como tú, la curiosidad simplemente se afianza y tengo que descargar un compilador / intérprete y probarlo. Probablemente aprenderá mucho más de las fortalezas y debilidades de un lenguaje funcional dado.


Para mí, la atracción de Haskell es la promesa de la corrección garantizada por el compilador. Incluso si se trata de partes puras del código.

He escrito mucho código de simulación científica, y me he preguntado muchas veces si había algún error en mis códigos anteriores, lo que podría invalidar mucho trabajo actual.


Para transmitir una opinión contraria: Steve Yegge escribe que los idiomas de Hindely-Milner carecen de la flexibilidad necesaria para escribir buenos sistemas :

HM es muy bonito, en un sentido matemático formal totalmente inútil. Maneja muy bien algunos constructos de cómputo; el envío de coincidencia de patrones encontrado en Haskell, SML y OCaml es particularmente útil. Como era de esperar, maneja torpemente algunas otras construcciones comunes y altamente deseables, pero explican esos escenarios diciendo que estás equivocado, en realidad no los quieres. Ya sabes, cosas como, oh, establecer variables.

Vale la pena aprender Haskell, pero tiene sus propias debilidades.


Para ver un ejemplo interesante, puede consultar: http://en.literateprograms.org/Quicksort_(Haskell)

Lo interesante es observar la implementación en varios idiomas.

Lo que hace que Haskell sea tan interesante, junto con otros lenguajes funcionales, es el hecho de que tienes que pensar diferente sobre cómo programar. Por ejemplo, generalmente no utilizará los bucles for o while, pero usará la recursión.

Como se mencionó anteriormente, Haskell y otros lenguajes funcionales sobresalen con aplicaciones paralelas de procesamiento y escritura para trabajar en múltiples núcleos.


Parte del alboroto es que la pureza y el tipado estático permiten el paralelismo combinado con optimizaciones agresivas. Los lenguajes paralelos están muy calientes ahora con multinúcleo siendo un poco perturbador.

Haskell le ofrece más opciones de paralelismo que prácticamente cualquier lenguaje de propósito general, junto con un compilador de código nativo rápido. Realmente no hay competencia con este tipo de soporte para estilos paralelos:

Entonces, si le importa hacer su trabajo multinúcleo, Haskell tiene algo que decir. Un gran lugar para comenzar es con el tutorial de Simon Peyton Jones sobre programación paralela y concurrente en Haskell .


Pasé el último año aprendiendo a Haskell y escribiendo un proyecto bastante grande y complejo en él. (El proyecto es un sistema de comercio de opciones automatizado, y todo, desde los algoritmos de negociación hasta el análisis y manejo de datos de mercado de baja velocidad y alta velocidad, se realiza en Haskell). Es mucho más conciso y fácil de entender (para aquellos con fondo apropiado) que una versión de Java, así como extremadamente robusto.

Posiblemente, la mayor victoria para mí ha sido la capacidad de modularizar el flujo de control a través de elementos tales como monoides, mónadas, etc. Un ejemplo muy simple sería el monoide que ordena; en una expresión como

c1 `mappend` c2 `mappend` c3

donde c1 y así sucesivamente devuelven LT , EQ o GT , c1 devuelve EQ hace que la expresión continúe, evaluando c2 ; si c2 devuelve LT o GT ese es el valor del todo, y c3 no se evalúa. Este tipo de cosas se vuelve considerablemente más sofisticado y complejo en cosas como generadores de mensajes monadic y analizadores sintácticos donde puedo transportar diferentes tipos de estado, tener diferentes condiciones de aborto, o puede querer decidir por cualquier llamada particular si el aborto realmente significa "no procesar más" o significa "devolver un error al final, pero continuar procesando para recopilar más mensajes de error".

Esto es todo lo que toma algo de tiempo y probablemente un poco de esfuerzo para aprender, y por lo tanto puede ser difícil hacer un argumento convincente para aquellos que aún no conocen estas técnicas. Creo que el tutorial de All About Monads ofrece una demostración bastante impresionante de una faceta de esto, pero no esperaría que alguien que no esté familiarizado con el material ya lo "obtenga" en la primera, o incluso la tercera, lectura cuidadosa.

De todos modos, hay muchas otras cosas buenas también en Haskell, pero esta es una pregunta importante que no veo mencionada tan a menudo, probablemente porque es bastante compleja.


Si puedes entender el sistema de tipos en Haskell, creo que en sí mismo es todo un logro.


Una de las cosas que encuentro genial cuando se trata de algoritmos o problemas matemáticos es la evaluación vaga de cálculos inherentes de Haskell, que solo es posible debido a su naturaleza funcional estricta.

Por ejemplo, si quiere calcular todos los números primos, podría usar

primes = sieve [2..] where sieve (p:xs) = p : sieve [x | x<-xs, x `mod` p /= 0]

y el resultado es en realidad una lista infinita. Pero Haskell lo evaluará desde la derecha, por lo que siempre que no intente hacer algo que requiera toda la lista, puede seguir utilizándolo sin que el programa se quede atascado en el infinito, como por ejemplo:

foo = sum $ takeWhile (<100) primes

que suma todos los números primos menores que 100. Esto es bueno por varias razones. Antes que nada, solo necesito escribir una función principal que genere todos los números primos y luego estoy casi listo para trabajar con números primos. En un lenguaje de programación orientado a objetos, necesitaría algún modo de decirle a la función cuántos primos debería calcular antes de volver, o emular el comportamiento de la lista infinita con un objeto. Otra cosa es que, en general, terminas escribiendo código que expresa lo que quieres calcular y no en qué orden evaluar las cosas; en cambio, el compilador hace eso por ti.

Esto no solo es útil para listas infinitas, de hecho se usa sin que usted lo sepa todo el tiempo cuando no hay necesidad de evaluar más de lo necesario.


no tiene construcciones de bucle no muchos idiomas tienen este rasgo.


La memoria transaccional de software es una forma genial de manejar la concurrencia. Es mucho más flexible que el paso de mensajes y no es propenso a interbloqueos como mutexes. GHC''s implementación de STM de GHC''s se considera una de las mejores.