Ich versuche, das pipes
-Paket zu lernen, indem ich meine eigene sum
-Funktion schreibe, und ich werde ratlos. Ich möchte die Utility-Funktionen nicht von Pipes.Prelude
verwenden (da es sum
und fold
und andere Funktionen hat, die es trivial machen) und nur die Informationen verwenden, die in Pipes.Tutorial
beschrieben sind. Das Tutorial spricht nicht über die Konstruktoren von Proxy
, aber wenn ich in der Quelle von sum
und fold
nachschaue, verwendet es diese Konstruktoren und ich frage mich, ob es möglich ist, meine sum
-Funktion ohne Wissen von zu schreiben diese Low-Level-Details.
Ich habe Probleme damit, herauszufinden, wie diese Funktion weiterhin Werte aufnehmen kann, solange Werte verfügbar sind, und diese Summe dann irgendwie an den Benutzer zurücksende. Ich denke, der Typ wäre:
%Vor%Es scheint mir, dass dies funktionieren könnte, weil diese Funktion Werte konsumieren könnte, bis keine mehr vorhanden sind, und dann die endgültige Summe zurückgeben. Ich würde es so verwenden:
%Vor% Die Funktion in Pipes.Prelude
hat jedoch stattdessen die folgende Signatur:
Also ich denke, das ist meine erste Hürde. Warum verwendet die sum
-Funktion ein Producer
als Argument und nicht >->
zum Verbinden?
Zu guter Letzt habe ich nach der Antwort von danidiaz folgendes gefunden:
%Vor% Consumers
sind eigentlich ziemlich begrenzt in dem, was sie tun können. Sie können das Ende der Eingabe nicht erkennen ( pipes-parse verwendet dafür eine andere Technik) und wenn es welche gibt Ein anderer Teil der Pipeline stoppt (zum Beispiel der Producer
stromaufwärts) dieser Teil ist derjenige, der den Ergebniswert für die Pipeline bereitstellen muss. Die Summe in den Rückgabewert von Consumer
zu setzen wird also im Allgemeinen nicht funktionieren.
Einige Alternativen sind:
Implementieren Sie eine Funktion, die direkt mit Producer
internals arbeitet, oder vielleicht eine Hilfsfunktion wie next
. Es gibt Adapter dieses Typs, die Producer
-Daten an "intelligentere" Konsumenten liefern können, wie Fold
s von der foldl Paket.
Verwenden Sie weiterhin Consumer
, aber anstatt die Summe in den Rückgabewert von Consumer
zu setzen, verwenden Sie WriterT
als Basismonade mit einem Sum Int
Monoid als Akkumulator. Auf diese Weise können Sie auch dann, wenn% code_% zuerst stoppt, den Writer ausführen, um zum Akkumulator zu gelangen. Diese Lösung ist jedoch wahrscheinlich weniger effizient.
Beispielcode für den Producer
-Ansatz: