Ich versuche ein kleines Experiment in Haskell und frage mich, ob es möglich ist, Faulheit zu nutzen, um IO zu verarbeiten. Ich würde gerne eine Funktion schreiben, die einen String (eine Liste von Chars) nimmt und träge einen String erzeugt. Ich würde es dann mögen, wenn ich die Buchstaben von IO langsam füttern könnte, so würde jedes Zeichen so bald wie möglich verarbeitet werden, und die Ausgabe würde erzeugt werden, sobald die benötigten Zeichen verfügbar wären. Ich bin mir jedoch nicht ganz sicher, ob / wie ich aus der Eingabe in der IO-Monade eine faule Liste von Zeichen erzeugen kann.
Regelmäßige String IO in Haskell ist faul. Ihr Beispiel sollte also einfach funktionieren.
Hier ist ein Beispiel, das die Funktion 'interact' verwendet, die eine Funktion auf einen trägen Zeichenstrom anwendet:
%Vor%Lassen Sie uns den Buchstaben "e" aus dem Eingabestrom träge herausfiltern (d. h. in konstantem Raum laufen):
%Vor%Sie können getContents und putStr auch verwenden, wenn Sie möchten. Sie sind alle faul.
Wird ausgeführt, um den Buchstaben "e" aus dem Wörterbuch zu filtern:
%Vor%also sehen wir, dass es in einem konstanten 2M Fußabdruck lief.
Die einfachste Methode zum Ausführen von Lazy IO umfasst Funktionen wie interact
, readFile
, hGetContents
und so, wie dons sagt; Es gibt eine ausführlichere Diskussion darüber in dem Buch Real World Haskell , das Sie vielleicht nützlich finden könnten. Wenn der Speicher mir dient, werden all diese Funktionen eventuell mit dem unsafeInterleaveIO
that ephemient Erwähnungen implementiert, so dass Sie auch Ihre eigenen Funktionen auf diese Weise erstellen können, wenn Sie möchten.
Auf der anderen Seite kann es sinnvoll sein, zu beachten, dass unsafeInterleaveIO
genau das ist, was auf der Verpackung steht: unsafe IO . Wenn man es benutzt - oder darauf basierende Funktionen - bricht Reinheit und referentielle Transparenz . Dies ermöglicht, dass scheinbar reine Funktionen (dh, die keine IO
-Aktion zurückgeben) die Außenwelt bei der Auswertung beeinflussen, unterschiedliche Ergebnisse von denselben Argumenten erzeugen und all diese anderen unangenehmen Dinge. In der Praxis verursachen die meisten sinnvollen Methoden zur Verwendung von unsafeInterleaveIO
keine Probleme, und einfache Fehler führen normalerweise zu offensichtlichen und leicht zu diagnostizierenden Fehlern, aber Sie haben einige schöne Garantien verloren.
Es gibt natürlich Alternativen; Sie können verschiedene Bibliotheken auf Hackage finden, die eingeschränkte, sicherere Lazy IO oder konzeptionell unterschiedliche Ansätze . Da jedoch im praktischen Einsatz nur selten Probleme auftreten, sind die meisten Menschen geneigt, sich an die eingebauten, technisch unsicheren Funktionen zu halten.
%Vor%
unsafeInterleaveIO
allosIO
Berechnung verzögert verschoben werden. Wenn ein Wert vom TypIO a
übergeben wird, wirdIO
nur ausgeführt, wenn der Wert vona
angefordert wird. Dies wird verwendet, um das Lesen von faulen Dateien zu implementieren, sieheSystem.IO.hGetContents
.
Zum Beispiel ist main = getContents >>= return . map Data.Char.toUpper >>= putStr
faul; Wenn Sie Zeichen an stdin übergeben, erhalten Sie Zeichen auf stdout.
(Dies entspricht dem Schreiben von main = interact $ map Data.Char.toUpper
, wie in der Antwort von dons.)
Tags und Links haskell io lazy-evaluation