Ich möchte Änderungen in der Staatsmonade verfolgen. Dies funktioniert nicht:
%Vor%Es wird nichts gedruckt (außer dem Endergebnis des Drucks in der Hauptfunktion, der korrekt aktualisiert wurde).
Irgendwelche Ideen oder Alternativen, um den Zustand zu verfolgen? Ich möchte dies für die Überprüfung der Richtigkeit einer Projekt-Euler-Lösung verwenden.
Das Problem in Ihrem Fall ist, dass traceThis
niemals ausgewertet wird. Haskell ist eine faule Sprache, daher wertet es nur Ausdrücke aus, die benötigt werden. Und da Sie das Berechnungsergebnis nicht nur den Status auswerten, ist es nicht notwendig, traceThis
in compute
zu bewerten. Wenn Sie zum Beispiel
Dann wird der Ergebniswert der statusbehafteten Berechnung zusammen mit dem Aufruf von traceThis
ausgewertet.
Eine bessere Option wäre die Definition einer monadischen Funktion, die das Ausdrucken des Ergebniswerts erzwingt, wenn ein Teil der monadischen Berechnung ausgewertet wird:
%Vor% Update: Dies kann zu einer beliebigen Monade verallgemeinert werden. Der Hauptpunkt ist, dass trace
die monadische Berechnung umbrechen muss, nicht nur den Wert innerhalb, so dass sie ausgewertet wird, wenn >>=
ausgewertet wird, unabhängig davon, ob der Wert innerhalb ausgewertet wird oder nicht:
Hier ist eine Alternative. Verwende StateT s IO
als deine Monade:
Jetzt können Sie IO
-Aktionen überall mit lift
verschachteln.
Um mehr über Monadtransformatoren zu erfahren, empfehle ich Ihnen, die exzellente Einführung zu lesen: Monad Transformers - Step für Schritt .
Wenn Sie execState
aufrufen, fragen Sie nur nach dem endgültigen Status, nicht nach dem Wert, der von der compute
-Funktion zurückgegeben wird. liftM
dagegen hebt die Funktion traceThis
auf eine Aktion in der State
-Monade auf, die den Status nicht berührt. Daher wird traceThis
aufgrund von Faulheit nur aufgerufen, wenn Sie den von compute
zurückgegebenen Wert erzwingen, um ausgewertet zu werden. Im Allgemeinen müssen Sie sicherstellen, dass% ce_de% richtig funktioniert, dass der Wert, auf den Sie ihn anwenden, ausgewertet wird.
trace
eignet sich generell nur für schnelles Debugging - es ist kein sehr leistungsfähiges Logging-System und kann aufgrund von Faulheit schwierig zu benutzen sein. Wenn Sie nach einer Möglichkeit suchen, dies robuster zu machen, könnten Sie Ihrem Statustupel ein weiteres Element (vielleicht eine Liste von Strings) hinzufügen und die Debug.Trace
-Funktion dazu veranlassen, Protokollmeldungen zu schreiben.
Tags und Links haskell