performance - ¿Cuánto tiempo te toma sentir cómodo con Haskell?
(5)
El objetivo no es escribir rápidamente el código Haskell, sino escribir rápidamente el código Haskell. Cuando llegue allí y necesite acelerar su código (er), comience a optimizar (o use el FFI, no tiene que olvidar sus habilidades en C ++). En Haskell, primero busca elegancia, fiabilidad y facilidad de mantenimiento. Agregaría perfiles a mi Haskell-fu, para que no pierda el tiempo optimizando lo que no se usa. Y recuerda no optimizar de forma prematura.
Soy un programador de C / C ++ OK. Encuentro a Haskell muy intrigante. Pero me parece que, aunque es relativamente fácil escribir código Haskell limpio, ya que imita muy bien las matemáticas (con las que me siento muy cómodo), es muy difícil escribir código limpio en Haskell que corre rápido.
Una versión más rápida de quicksort de Haskell es muy larga y aterradora, que no se parece a la implementación ingenua pero corta (dos líneas), limpia e intuitiva. La versión larga y aterradora de Haskell es en realidad mucho más lenta que la parte más corta y más simple del contador C.
¿Es porque el compilador de Haskell actual es demasiado tonto o es simplemente imposible para los mortales (aparte de SJP por supuesto) escribir rápidamente el código de Haskell?
Hay una razón muy específica por la que el quicksort no es tan rápido en Haskell. Es un ejemplo parecido a Dios de un algoritmo que tiene hackers brillantes entretejidos en cómo funciona; lo que quiero decir con hackers en este caso es el tipo de técnicas que un verdadero devoto de Haskell consideraría innecesariamente peligrosas y no matemáticas. La implementación original hizo todos los esfuerzos posibles para romper las reglas que Haskell se impone a sí mismo: el quicksort genuino funciona sobrescribiendo las ranuras de almacenamiento con nueva información. Esto es muy doloroso de hacer en Haskell, que encuentra que es mucho más fácil hacer copias completas de la información existente.
Así que, aunque esa versión ingenua de Haskell de dos líneas capta algo de la esencia de la oferta rápida (hace el mismo número de comparaciones de claves), en realidad no es de orden rápido. Le falta una gran parte del genio que entró en él, que aprovechó al máximo la capacidad de ajustar el estado de los valores existentes. Entonces hace un gran número de copias intermedias de las piezas de la lista.
Especulación: ¿podría un compilador de Haskell analizar su código, aplicando el mismo razonamiento que Hoare (inventor de quicksort) y descubrir que podría optimizarlo al volver a implementarlo por completo? Posiblemente.
La razón es que la base matemática de las computadoras es diferente de la base matemática de Haskell y los lenguajes funcionales en general.
Para probar los problemas que enfrenta el compilador ... Traduzca el programa Haskell a C, manteniéndolo lo más cercano posible al original, luego intente optimizar ese código C (sin reescribirlo desde cero en C-way)
No es tonto, pero los lenguajes funcionales no están hechos para el rendimiento, y la notación concisa matemáticamente simple no es gratis.
Por lo tanto, para responder a la pregunta en el título, es probable que se sienta como en casa con los conceptos básicos de Haskell en poco tiempo. Especialmente si ya está familiarizado con la programación funcional. Las cosas que realmente hacen que Haskell se destaque, como la pereza, las clases de tipo, las familias tipográficas y, por supuesto, las temidas mónadas (y flechas) es probable que requieran más tiempo para comprender y acostumbrarse. Hay buenos recursos para aprender el idioma, muchos disponibles de forma gratuita, junto con una comunidad útil, así que diría que probablemente te encuentres en camino a sentirte cómodo dentro de una semana o dos de estudio semi serio ;-)
Creo que vale la pena, al igual que algunas personas argumentan que vale la pena aprender Lisp, incluso si nunca lo usarás para nada. Vale la pena porque te convierte en un mejor programador, te hace pensar de manera diferente. Yo diría que Haskell tiene un efecto similar.
Usted hace dos preguntas diferentes: aprendizaje y rendimiento.
- Me llevó alrededor de un mes familiarizarme con la programación funcional mediante la recursión, la coincidencia de patrones, el
map
, elfilter
y elfold
. Hice todo eso con ML pero se tradujo a Haskell muy fácilmente. - Me llevó dos o tres años rodear mi cabeza con mónadas, pero eso es porque leo las cosas equivocadas. Creo que hay mejores tutoriales ahora. Pero si estás comenzando, evita las mónadas por un tiempo.
- Me llevó varios meses hacer bien en la creación de nuevas clases de tipos, pero el uso de las existentes fue fácil.
- Todavía no estoy seguro de tener el truco de la evaluación perezosa . Pero me encanta la pureza de Haskell y tiendo a considerar la evaluación perezosa como un accidente infeliz que solo unas pocas personas (como John Hughes) saben cómo explotar.
Has observado un problema de rendimiento solo porque has adaptado un algoritmo cargado con mutación, que Tony Hoare diseñó para lenguajes imperativos, y trataste de traducir a Haskell. En Haskell, como en cualquier otro lenguaje funcional, la operación costosa es la asignación . Intenta escribir un tipo de combinación y encontrarás que es simple y funciona muy bien.
¿Cómo evitas cometer errores similares en el futuro? Eche un vistazo al libro de Chris Okasaki Estructuras de datos puramente funcionales . Gran libro, y te ayudará a aprender la ''forma funcional de hacer las cosas'' sin renunciar al rendimiento.