Rate My Number, ein monadischer Kopfschmerz

8

Um meine Fähigkeiten in Haskell zu testen, entschied ich, dass ich das allererste Spiel implementieren wollte, das Sie in Land of Lisp / Reich der Schläger finden. Das "Raten Sie meine Nummer" Spiel. Das Spiel benötigt einen veränderbaren Status, da es ständig die oberen und unteren Grenzen aktualisieren muss, damit das Programm den Wert, an den der Benutzer denkt, einholen kann.

Es geht ein bisschen so:

%Vor%

Nun, so etwas ist meines Wissens in Haskell nicht ganz möglich, indem es eine Funktion der REPL aufruft, die den globalen veränderlichen Zustand modifiziert, und das Ergebnis unmittelbar danach ausdruckt, da es gegen das Prinzip der Unveränderlichkeit verstößt. Daher muss die gesamte Interaktion innerhalb einer IO und / oder State monad liegen. Und da stecke ich fest.

Ich kann nicht in der Lage sein, mich daran zu erinnern, die IO monad und die State monad zu kombinieren, damit ich Input, Ergebnisse und Status in derselben Funktion erhalten kann.

>

Folgendes habe ich bis jetzt:

%Vor%

Alles, was ich jetzt tun muss, ist einen Weg zu finden

  • erste Schätzung drucken
  • Befehl empfangen, der eine kleinere / größere Nummer benötigt
  • ändert den Status entsprechend
  • rufe die Funktion rekursiv auf, so dass sie erneut rät

Wie kombiniere ich IO und State auf elegante Weise, um dies zu erreichen?

Hinweis: Ich bin mir bewusst, dass dies wahrscheinlich ohne die Verwendung von Staat überhaupt erreicht werden kann; aber ich möchte, dass es dem Original treu bleibt

    
Electric Coffee 27.01.2015, 19:21
quelle

4 Antworten

12

Sie können verschiedene Monaden mit Hilfe von Monade-Transformatoren kombinieren - in diesem Fall StateT . Sie können Ihren vorhandenen Code verwenden, indem Sie die Typignaturen so ändern, dass StateT :

verwendet wird %Vor%

Dann können Sie eine Funktion schreiben, um das Spiel mit einem Zustandsparameter auszuführen:

%Vor%

Sie verwenden liftIO , um eine IO Aktion in die StateT Bound IO Monade zu heben, damit Sie zur Eingabe auffordern und die nächste Zeile lesen können.

Schließlich kannst du das Spiel mit runStateT :

ausführen %Vor%     
Lee 27.01.2015, 19:58
quelle
7

Was Sie fragen, ist irgendwie möglich ...

%Vor%

Vergiss nicht, wie viel Redundanz in diesem Code steckt, das war nur ein kurzer Beweis für das Konzept. Hier ist eine Beispielsitzung:

%Vor%

Verschachtelte IO -Typen können Spaß machen und nützlich sein.

    
Carl 27.01.2015 20:03
quelle
2

Sie müssen in diesem Beispiel die Zustandsmonade überhaupt nicht verwenden. Hier ist ein Beispiel, das den Status als Parameter übergibt:

%Vor%

Ansonsten suchen Sie nach Monadetransformatoren . Zum Beispiel mit StateT:

%Vor%

Sehen Sie dieses Kapitel von Real World Haskell für ein Tutorial zum Thema Monadetransformatoren.

    
hpdeifel 27.01.2015 19:45
quelle
1

Hier ist eine Lösung mit dem StateT -Transformator. Bemerkenswerte Punkte:

  1. Es liest Benutzereingaben mit getLine anstelle der REPL.
  2. Es liest sich sehr nach einem imperativen Programm, außer dass Sie liftIO zu irgendwelchen IO-Aktionen hinzufügen müssen.
  3. Sie führen die Schleife mit runStateT aus, wobei Sie auch den Anfangszustand angeben.

Das Programm:

%Vor%     
ErikR 27.01.2015 19:44
quelle

Tags und Links