Wie verwende ich Debug.Trace.trace in der Statusmonade?

8

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.

    
somesoaccount 07.08.2012, 12:22
quelle

3 Antworten

11

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

drucken %Vor%

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:

%Vor%     
Petr Pudlák 07.08.2012, 12:49
quelle
4

Hier ist eine Alternative. Verwende StateT s IO als deine Monade:

%Vor%

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 .

    
Gabriel Gonzalez 07.08.2012 12:40
quelle
4

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.

    
Alexander Dunlap 07.08.2012 12:44
quelle

Tags und Links