2016-04-15 6 views
0

Ist es möglich, das Ergebnis einer staatlichen Monade in Haskell zu drucken?Wie drucken Sie das Ergebnis einer staatlichen Monade in Haskell?

Ich versuche, staatliche Monaden zu verstehen und in einem Buch, das ich verfolgt habe, liefert den Code unten für die Erstellung einer staatlichen Monade, aber ich habe mit diesem Thema zu kämpfen, wie ich den Prozess visuell nicht sehen kann, dh das Ende sehen Ergebnis.

newtype State s a = State { runState :: s -> (a,s)} 

instance Monad (State s) where 
    return x = State $ \s -> (x,s) 
    (State h) >>= f = State $ \s -> let (a, newState) = h s 
             (State g) = f a 
            in g newState 
+1

"So drucken Sie eine State Monad" ist eine völlig andere Frage als "wie das _result_ einer State Monad" drucken, zumindest wenn ich ersteres als Ausdruck einer _State_Aktion_ und letzterer als _printing_der_Monade verstehe Ergebnis der einmaligen Durchführung einer 'State'-Aktion. Was meinst du? – leftaroundabout

+0

@leftaroundabout Ergebnis sorry. –

Antwort

2

Der Code, den Sie geliefert haben definiert die Art der Sache State s a ist. Und es sagt auch, dass State s eine Monade ist - das heißt, die Art der Sache State s ist mit der Monad Typklasse/Schnittstelle konform. Dies bedeutet, dass Sie eine State s Berechnung an eine andere binden können (solange der Typ s in jedem gleich ist).

So ist Ihre Situation analog zu der von jemandem, der die Art der Sache definiert hat, die ein Map ist, und hat auch Code geschrieben, der besagt, dass ein Map solchen und solchen Schnittstellen entspricht, aber wer keine Karten hat, und hat noch keine Berechnungen mit ihnen ausgeführt. Es gibt nichts zu drucken.

Ich nehme an, Sie das Ergebnis der Auswertung oder Ausführung Ihres Staates Maßnahmen sehen wollen, aber Sie haben keine Istzustand Aktionen noch definiert, noch haben Sie runState genannt (oder evalState oder execState) auf sie. Vergessen Sie nicht, dass Sie auch einen Anfangszustand angeben müssen, um die Berechnung auszuführen.

Also vielleicht beginnen mit s und a einige Arten sein. Z.B. lasst sInt sein und aInt sein. Jetzt könntest du ein paar Fn schreiben, z.B. f :: Int -> (Int, Int) und g :: Int -> (Int, Int). Vielleicht dekrementiert eine Funktion den Zustand, gibt den neuen Zustand und Wert zurück, und eine andere Funktion inkrementiert den Zustand und gibt den neuen Zustand und Wert zurück. Dann könnten Sie einen State Int Int aus f machen, indem Sie ihn in den State Konstruktor einpacken. Und Sie könnten >>= verwenden, um so viele Statusaktionen zusammenzufassen, wie Sie möchten. Schließlich können Sie hier runState verwenden, um den resultierenden Wert und den resultierenden Status zu erhalten, solange Sie auch einen Anfangszustand (z. B. 0) angeben.

+0

@liminishit Vielen Dank Ihre Antwort, es ist wirklich hilfreich! Ich habe eine Funktion f gemacht, um den Zustand zu erhöhen. Ich bin etwas unsicher, wie man den Ketten-Teil tut, sorry, wäre es möglich, dass du mir bitte ein Beispiel zeigst. Danke –

+0

Sei 'f = \ x -> (x + 1, x + 1)' und lass 'g = Staat (f) >> = Staat (f)'. Dies stellt eine Statusaktion dar, die den Status zweimal inkrementiert. 'runState g 0' sollte' (2,2) 'zurückgeben. Wenn "h = \ x -> return (x + 1, x + 1)" und j = "StateT (h) >> = StateT (h)" äquivalent ist, gibt "runStateT h 0" "(2, 2) '. Dies könnte Ihnen ein Gefühl geben, wie die 'State'-Monade funktioniert. Aber das Erstellen von Statusaktionen mit 'get'' put' und 'modify' aus einem Paket wie' mtl' oder 'transformers' ist normalerweise die Verwendung der' State'-Monade und ähnelt wirklich dem imperativen Stil, der Sie sein könnten gewohnt von einer imperativen Sprache. – liminalisht

4

Es ist generell nicht möglich, Funktionen sinnvoll zu drucken. Wenn die Domäne der Funktion klein ist, können Sie Data.Universe.Instances.Show aus dem Paket universe-reverse-instances importieren, um eine Show Instanz zu erhalten, die eine Lookup-Tabelle ausgibt, die semantisch der Funktion entspricht. Wenn Sie dieses Modul importieren, können Sie einfach deriving Show zu Ihrer newtype Deklaration hinzufügen, um State Aktionen über kleine Statusbereiche drucken zu können.

1

Wenn es nur das Ergebnis, das Sie wollen, und wenn Sie nur das Debuggen:

import Debug.Trace 
import Control.Monad.Trans.State 

action :: State [Int]() 
action = do 
    put [0] 
    modify (1:) 
    modify (2:) 
    get >>= traceShowM 
    modify (3:) 
    modify (4:) 
    get >>= traceShowM 
+0

danke, aber ich bekomme den Fehler nicht im Bereich für setzen, ändern, ändern, erhalten, ändern, ändern, bekommen? –

+0

Dies ist mit Funktionen von der Bibliothek zur Verfügung gestellt verfügbar durch den Import Control.Monad.Trans.State – Gurkenglas

+0

Vielen Dank, ich bekomme einen Fehler für "Mehrdeutiges Auftreten 'State' Es könnte sich entweder auf 'Main.State' oder 'Control.Monad .Trans.State.State '"[email protected] –