Ich habe einige Erfahrung mit dem Schreiben kleiner Werkzeuge in Haskell und finde es sehr intuitiv zu bedienen, insbesondere zum Schreiben von Filtern (unter Verwendung von Filtern interact
), die ihre Standardeingabe verarbeiten und an die Standardausgabe weiterleiten.
Kürzlich habe ich versucht, einen solchen Filter für eine Datei zu verwenden, die etwa 10-mal so groß war wie gewöhnlich, und ich habe eine Stack space overflow
Fehlermeldung erhalten.
Nach einigem Lesen (z. B. hier und hier ) habe ich zwei Richtlinien identifiziert, um Stapelspeicher zu sparen (erfahrene Haskeller, bitte korrigieren Sie mich, wenn ich etwas schreibe, das nicht korrekt ist):
- Vermeiden Sie rekursive Funktionsaufrufe, die nicht tail-rekursiv sind (dies gilt für alle funktionalen Sprachen, die die Tail-Call-Optimierung unterstützen).
- Einführung
seq
in die Erzwingung einer frühen Auswertung von Unterausdrücken, damit die Ausdrücke nicht zu groß werden, bevor sie reduziert werden (dies gilt speziell für Haskell oder zumindest für Sprachen, die eine verzögerte Auswertung verwenden).
Nach fünf oder sechs seq
Aufrufen in meinem Code läuft mein Tool wieder reibungslos (auch auf den größeren Daten). Allerdings finde ich den Originalcode etwas besser lesbar.
Da ich kein erfahrener Haskell-Programmierer bin, wollte ich fragen, ob das Einführen seq
auf diese Weise eine gängige Praxis ist und wie oft es normalerweise seq
im Haskell-Produktionscode vorkommt. Oder gibt es Techniken, die es ermöglichen, zu häufiges Verwenden seq
zu vermeiden und dennoch wenig Stapelspeicher zu verwenden?