Dieses Programm:
%Vor%Kompiliert. Dieses Programm:
%Vor%Kompiliert nicht mit dem folgenden Fehler:
%Vor%Warum?
Hinweis: Dieser Beitrag ist in literarischem Haskell geschrieben. Sie können es als Unsafe.lhs speichern und es in Ihrem GHCi versuchen.
Vergleichen wir die Typen der verschiedenen Zeilen:
%Vor% Sie sind aufgrund des Typs $
nicht gleichwertig:
Während Sie etwas brauchen würden
%Vor%was nicht legal ist.
Sehen wir uns jedoch an, was Sie eigentlich tun wollen.
%Vor% Die Dinge wurden aufgrund des polymorphen ersten Arguments unsafeModify
mods
unordentlich. Dein ursprünglicher Typ
sagt uns, dass es sich um eine Liste von Funktionen handelt, bei denen jede Funktion polymorph ist und der Parameter s
, so dass jede Funktion ein anderes s
verwenden kann. Das ist jedoch zu viel. Es ist in Ordnung, wenn das s
über die gesamte Liste geteilt wird:
Schließlich wollen wir alle Funktionen in der gleichen ST
Berechnung verwenden, daher kann der Typ des Stromstatus-Tokens s
gleich sein. Wir enden mit
Und nun kompiliert Ihr Code glücklich, unabhängig davon, ob Sie ($ mvec) (mods !! 0)
, (mods !! 0) mvec
oder mapM_
verwenden, weil s
jetzt korrekt durch runST
in der gesamten Liste korrigiert wird.
(Dies sollte wahrscheinlich ein Kommentar sein, aber ich brauche mehr Platz.)
Leider funktionieren impredikative Typen in GHC nicht sehr gut, wie @dfeuer betonte. Betrachten Sie dieses Beispiel:
%Vor%Es kompiliert erfolgreich, wenn auch mit einer Warnung wegen des Typs Loch:
%Vor% Wir könnten versuchen, die Erweiterung PartialTypeSignatures
zu entfernen und die Lücke mit ihrem Typ forall s. MV.MVector s Int -> ST s ()
zu füllen. Aber das scheitert schrecklich:
Der letzte forall
wird auf die oberste Ebene gehievt, und nun sagt GHC, dass das erste Argument von (!!)
eine Liste monomorpher Elemente sein muss [MV.MVector s1 Int -> ST s1 ()]
trotz unserer Annotation! Grundsätzlich hat GHC zwei Möglichkeiten:
GHC wählt die zweite und schlägt fehl. Nur mit einer partiellen Typ-Signatur konnte ich die zweite Wahl entfernen, so dass GHC gezwungen war, das Richtige zu tun.
Wenn wir nur eine explizite Anwendung wie in GHC Core hätten, hätten wir (!!) @ (forall s. ...)
schreiben können, aber leider nicht.
Tags und Links haskell impredicativetypes