Das verhindert, dass s
Gegenstände innerhalb der ST
Monade nach außen aus der ST
Monade austreten .
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 Extra s
. Denken Sie daran, dass runST
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 bewerten a
:
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 der s
außerhalb des forall
In "" entkommen "ist runST
. Typvariablen müssen immer auf der Innenseite von a erscheinen forall
, und Haskell erlaubt forall
überall implizite Quantifizierer. Es gibt einfach keine Regel, mit der Sie den Rückgabetyp von sinnvoll herausfinden können a
.
Ein weiteres Beispiel mit forall
: Um klar zu zeigen, warum Sie nicht zulassen können, dass Dinge einem entkommen forall
, 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
Dies ist natürlich f id
ein Fehler, da er entweder eine Liste Char
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 mit ST
.
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 die IO
Monade, jedoch mit einer etwas anderen Schnittstelle. Wenn Sie die ST
Monade verwenden, erhalten Sie tatsächlich unsafePerformIO
oder das Äquivalent hinter den Kulissen. Der Grund, warum Sie dies sicher tun können, liegt in der ST
Typensignatur aller verwandten Funktionen, insbesondere des Teils mit dem forall
.