¿Qué tan dependiente es la habilidad de Haskell en la memoria de trabajo?

No muy

El sistema de tipos realmente lo ayuda asegurándose de que el código se documenta a sí mismo y señalando los errores que cometió . Así que si no recuerdas algo, puedes buscarlo trivialmente. Y si no lo busca, obtendrá un error de tipo que le dice qué olvidó, dónde.

He estado usando Haskell durante años y todavía no recuerdo qué orden han foldl los argumentos para foldl y foldr . (¡Son diferentes entre los dos!) Cada vez que necesito usar un pliegue, lo cual es bastante frecuente, simplemente me acerco a GHCi:

  Preludio>: t foldl
 foldl :: (a -> b -> a) -> a -> [b] -> a

Jajaja El acumulador va primero .

Hago un montón de listas de disputas¹. Pero todavía no recuerdo la mayoría de las funciones de la lista. Es muy útil tener una idea de lo que es posible , pero no necesita recordar ningún detalle. Cuando necesito hacer el código de la lista, simplemente me dirijo a GHCi, carga el módulo de lista y escribo:

  Prelude Data.List>: Browse Data.List
 (\\) :: Eq a => [a] -> [a] -> [a]
 delete :: Eq a => a -> [a] -> [a]
 deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]
 deleteFirstsBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
 ... 129 o así funciones en total

Luego busco el fragmento del nombre que recuerdo (“hmm, esto suena como una función de ‘intervalo’) o el tipo básico que necesito. También ayuda que ejecute GHCi dentro de un búfer de Emacs, lo que hace que navegar por grandes cantidades de salida sea trivial.

Esto funciona realmente bien para la mayoría de los módulos que uso: las firmas de tipo en Haskell son sorprendentemente expresivas.

Para las cosas más difíciles, saco el buen nombre de Hoogle, que es un motor de búsqueda de API de Haskell que es muy inteligente en la búsqueda de tipos. ¿Cómo puedo unir un montón de cuerdas con un separador? (¡Esta función tiene un nombre realmente estúpido!)
El segundo resultado es el correcto. Lo encontró a pesar de que ingresé un tipo que era demasiado específico con los argumentos al revés . Es bueno (En serio, ¿quién llama a esto “intercalate”?)

En general, el sistema de tipos significa que en realidad tengo que recordar menos cosas que en otros idiomas.

Dicho esto, todavía hay algunos bordes en los que necesito más memoria de trabajo que el promedio. El más rudo es con mensajes de error pobres . A menudo, lo que dice un mensaje de error y el error real que lo causó son muy diferentes. Un ejemplo trivial es con typeclasses:

  * Dibujar> 1 + Verdadero

 : 10: 3:
     Ninguna instancia para (Num Bool) que surja de un uso de `+ '
     Posible solución: agregar una declaración de instancia para (Num Bool)
     En la expresión: 1 + Verdadero.
     En una ecuación para `it ': it = 1 + True

Tengo que traducir mentalmente “Ninguna instancia para …” como “Número esperado, obtuve Bool”.

En realidad, este ejemplo particular no es un problema real, pero hay ejemplos más complicados que lo son .

Una de las mayores dificultades que tuve para ser productivo en OCaml proveniente de un extenso historial de Haskell fue que mi intuición actual para los mensajes de error erróneos era en gran medida inútil. Este es el tipo de cosas donde la experiencia realmente ayuda y no la tuve.

Los mensajes de error me causan una verdadera frustración de vez en cuando. Pero, en general, es menos frustrante que la que me producen los errores que se colarían con un sistema de tipo peor o el ruido adicional que tendría con un sistema de inferencia más débil.

notas al pie
¹ Esto puede parecer extraño porque en muchos idiomas las listas enlazadas no son un gran tipo de datos. Sin embargo, dado que Haskell es perezoso, la disputa de listas a menudo está mucho más cerca de escribir bucles que de trabajar con estructuras de datos. Un montón de flujo de control complicado se puede expresar bien usando funciones de lista estándar, y aprovecho al máximo esto en Haskell.

Esta es una de las razones por las que soy un gran fan de tener la pereza de forma predeterminada.