J'ai une certaine expérience de l'écriture de petits outils dans Haskell et je le trouve très intuitif à utiliser, en particulier pour écrire des filtres (utilisant interact
) qui traitent leur entrée standard et la dirigent vers la sortie standard.
Récemment, j'ai essayé d'utiliser un tel filtre sur un fichier qui était environ 10 fois plus gros que d'habitude et j'ai eu une Stack space overflow
erreur.
Après avoir fait quelques lectures (par exemple ici et ici ), j'ai identifié deux lignes directrices pour économiser de l'espace de pile (Haskellers expérimentés, veuillez me corriger si j'écris quelque chose qui n'est pas correct):
- Évitez les appels de fonction récursifs qui ne sont pas récursifs (c'est valable pour tous les langages fonctionnels qui prennent en charge l'optimisation des appels de queue).
- Introduisez
seq
pour forcer une évaluation précoce des sous-expressions afin que les expressions ne deviennent pas trop grandes avant d'être réduites (ceci est spécifique à Haskell, ou au moins aux langues utilisant l'évaluation paresseuse).
Après avoir introduit cinq ou six seq
appels dans mon code, mon outil fonctionne à nouveau sans problème (également sur les données plus volumineuses). Cependant, je trouve que le code d'origine était un peu plus lisible.
Comme je ne suis pas un programmeur Haskell expérimenté, je voulais demander si l'introduction seq
de cette manière est une pratique courante et à quelle fréquence on verra normalement seq
dans le code de production Haskell. Ou existe-t-il des techniques qui permettent d'éviter d'utiliser seq
trop souvent tout en utilisant peu d'espace de pile?