Wie schreibe ich eine Haskell Pipes "sum" -Funktion?

8

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:

%Vor%

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%     
Ana 01.02.2016, 20:19
quelle

1 Antwort

5

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:

%Vor%     
danidiaz 01.02.2016, 21:23
quelle

Tags und Links