2016-10-28 2 views
0
data S = Sa Int 
type PMO = StateT Int (ErrorT String IO) 

cs :: S -> PMO() 
cs _ = do 
    mem <- get -- (*) 
    return() 

Ich habe die Zeile mit (*) markiert. Ich habe Zweifel, warum get Funktion aufgerufen werden kann. Ich weiß, dass get Funktion von State Monade ist, aber ich kann nicht sehen/begreifen, wie es bekannt ist, dass es solche Monade tatsächlich gibt. Ich sehe, dass der zurückgegebene Typ PMO ist, aber es ist nur ein zurückgegebener Wert. Was hat es mit get gemeinsam?Haskell und aufrufende Funktion.

Hauptsächlich habe ich eine Erfahrung mit imperativer Sprache Programmierung, so macht es mir Schwierigkeiten, es zu verstehen.

+0

Mögliches Duplikat von [Wie funktioniert dieser State-Monad-Code?] (Http://stackoverflow.com/questions/31506839/how-does-this-state-monad-code-works) – duplode

+0

('Get' arbeitet viel wie "frisch" in diesem Beispiel, außer dass die zugrunde liegende Funktion von "get" einfach "\ s -> (s, s)" ist, während "frisch" auch den Zustand ändert.) – duplode

Antwort

4

Überprüfen Sie die Art von get out:

get :: MonadState s m => m s 

Und da in der Art Signatur von cs haben Sie den Compiler gesagt, was m ist, get wird:

get :: StateT Int (ErrorT String IO) Int 

das ist nur eine einstellige Wert, keine Funktion. Woher kommt der Wert mem? Letztendlich stammt der Wert, den get liefert, aus dem anfänglichen Zustandswert, der von runStateT (oder execStateT oder evalStateT) geliefert wird.

Wenn das immer noch geheimnisvoll scheint, empfehle ich, zu studieren, wie die staatliche Monade funktioniert.

+0

"Und da in der Typ-Signatur von Wenn du dem Compiler gesagt hast, was m ist, bekommst du: "Ich kann es nicht verstehen. Kannst du mehr dazu sagen? – Gilgamesz

+1

In der Art von "Get" gibt es zwei Arten von Variablen. 's' ist der Typ des Zustandswerts und kann im Allgemeinen alles sein. 'm' muss ein Datentyp sein, der eine' MonadState' -Instanz hat. Ohne Typanmerkungen verwendet der Compiler die allgemeinsten Typen, die er verwenden kann. Ihre 'cs'-Funktion würde mit einem Typ wie' cs :: MonadStateam => b -> m() 'enden, da es nur zwei Dinge gibt, die der Compiler sicher kennt: Ihr' m' hat eine 'MonadState' -Instanz (weil Sie 'get' verwenden, und Sie geben den Wert'() 'zurück. – user2297560

+1

Jetzt, da Sie ihm explizit eine Typ-Signatur gegeben haben (was bei Definitionen auf oberster Ebene gut ist), fügen Sie dem Typ-Checker zusätzliche Einschränkungen hinzu. In der Tat haben Sie es genau gesagt, welche Instanz von 'MonadState' Sie wollen:' StateT Int (ErrorT String IO) '. Also geht "get" von "MonadState s m => m s" zu "StateT Int (ErrorT String IO) Int". (d. h. "m = StateT Int (ErrorT String IO)" und "s = Int") – user2297560