"Lazy IO" in Haskell?

8

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.

    
Edward 18.02.2010, 16:21
quelle

3 Antworten

14

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.

    
Don Stewart 18.02.2010, 17:18
quelle
7

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.

    
C. A. McCann 18.02.2010 18:11
quelle
3
%Vor%      

unsafeInterleaveIO allos IO Berechnung verzögert verschoben werden. Wenn ein Wert vom Typ IO a übergeben wird, wird IO nur ausgeführt, wenn der Wert von a angefordert wird. Dies wird verwendet, um das Lesen von faulen Dateien zu implementieren, siehe System.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.)

    
ephemient 18.02.2010 17:19
quelle

Tags und Links