Ich verstehe, dass die ST-Monade so etwas wie ein kleiner Bruder von IO ist, der wiederum die Staatsmonade mit zusätzlicher RealWorld
Magie ist. Ich kann Staaten Bild und ich kann vorstellen , dass Real World irgendwie in IO gesetzt wird, aber jedes Mal , wenn ich eine Art Unterschrift schreiben ST
die s
des ST Monade verwirrt mich.
Nehmen Sie zum Beispiel ST s (STArray s a b)
. Wie funktioniert das s
dort? Wird es nur verwendet, um eine künstliche Datenabhängigkeit zwischen Berechnungen aufzubauen, ohne wie Zustände in der Zustandsmonade (aufgrund der forall
) referenziert werden zu können ?
Ich werfe nur Ideen aus und würde es wirklich begrüßen, wenn jemand besser informiert wäre als ich, um es mir zu erklären.
ST
Monade zu verstehen . Sobald Sie verstanden haben, wie Rang-2-Typen steuern können, wer den für eine Typvariable verwendeten Typ auswählt, sollten Sie verstehen, wieST
Operationen Rang-2 verwenden, um zu verhindern, dass ihre Berechnungen illegal verwendet werden.a :: ST Int Int; a = return 2
ST
es sich um eine ganz normale Zustandsmonade handelt, außer dass ein unboxed Paar als Ausgabe der Zustandsfunktion verwendet wirdState# s -> (# State# s, a #)
, was es unpraktisch macht, damit umzugehen. Das Geheimnis liegt ganz darin,runST
dass es einen Typ vom Rang 2 hat, obwohl ST selbst keiner ist.Antworten:
Das verhindert, dass
s
Gegenstände innerhalb derST
Monade nach außen aus derST
Monade austreten .-- This is an error... but let's pretend for a moment... let a = runST $ newSTRef (15 :: Int) b = runST $ writeSTRef a 20 c = runST $ readSTRef a in b `seq` c
Okay, dies ist ein Typfehler (was gut ist! Wir wollen nicht
STRef
außerhalb der ursprünglichen Berechnung auslaufen!). Es ist ein Typfehler wegen des Extras
. Denken Sie daran, dassrunST
die Signatur hat:runST :: (forall s . ST s a) -> a
Dies bedeutet, dass
s
für die von Ihnen ausgeführte Berechnung keine Einschränkungen gelten müssen. Wenn Sie also versuchen zu bewertena
:a = runST (newSTRef (15 :: Int) :: forall s. ST s (STRef s Int))
Das Ergebnis hätte einen Typ
STRef s Int
, was falsch ist, da ders
außerhalb desforall
In "" entkommen "istrunST
. Typvariablen müssen immer auf der Innenseite von a erscheinenforall
, und Haskell erlaubtforall
überall implizite Quantifizierer. Es gibt einfach keine Regel, mit der Sie den Rückgabetyp von sinnvoll herausfinden könnena
.Ein weiteres Beispiel mit
forall
: Um klar zu zeigen, warum Sie nicht zulassen können, dass Dinge einem entkommenforall
, hier ein einfacheres Beispiel:f :: (forall a. [a] -> b) -> Bool -> b f g flag = if flag then g "abcd" else g [1,2] > :t f length f length :: Bool -> Int > :t f id -- error --
Dies ist natürlich
f id
ein Fehler, da er entweder eine ListeChar
oder eine Liste von zurückgeben würde,Int
je nachdem, ob der Boolesche Wert wahr oder falsch ist. Es ist einfach falsch, genau wie das Beispiel mitST
.Auf der anderen Seite, wenn Sie den
s
Typparameter nicht hätten , würde alles gut funktionieren , obwohl der Code offensichtlich ziemlich falsch ist.Wie ST tatsächlich funktioniert: In Bezug auf die Implementierung ist die
ST
Monade tatsächlich dieselbe wie dieIO
Monade, jedoch mit einer etwas anderen Schnittstelle. Wenn Sie dieST
Monade verwenden, erhalten Sie tatsächlichunsafePerformIO
oder das Äquivalent hinter den Kulissen. Der Grund, warum Sie dies sicher tun können, liegt in derST
Typensignatur aller verwandten Funktionen, insbesondere des Teils mit demforall
.quelle
realWorld#
direkt im Client-Code verwenden, um sie nachzuahmenrunSTRep
? Es ist natürlich eine schlechte Idee, aber ich frage mich, was der Schutz ist, abgesehen davon,realworld#
dass er ein offensichtlich unsicherer Wert ist, der in einem Programm verwendet werden kann. hackage.haskell.org/package/base-4.6.0.1/docs/src/…s
existiert nur auf Typebene.Dies
s
ist nur ein Hack, der das Typsystem davon abhält, Dinge zu tun, die unsicher wären. Zur Laufzeit "macht" es nichts. Der Typprüfer lehnt lediglich Programme ab, die zweifelhafte Dinge tun. (Es handelt sich um einen sogenannten Phantomtyp , der nur im Kopf des Typprüfers vorhanden ist und zur Laufzeit nichts beeinflusst.)quelle