Lassen Sie uns blutig sein. Wir müssen alles quantifizieren und den Bereich der Quantifizierung angeben. Werte haben Typen; Dinge auf Typenebene haben Arten; Arten leben in BOX
.
f1 :: forall (k :: BOX).
(forall (a :: k) (m :: k -> *). m a -> Int)
-> Int
f2 :: (forall (k :: BOX) (a :: k) (m :: k -> *). m a -> Int)
-> Int
nun in keinem Beispiel Typ ist k
explizit quantifiziert, so ghc entscheiden, wo diese forall (k :: BOX)
, legte auf der Grundlage, ob und wo k
erwähnt wird. Ich bin mir nicht ganz sicher, ob ich die Politik wie gesagt verstehe oder bereit bin, sie zu verteidigen.
Ørjan gibt ein gutes Beispiel für den Unterschied in der Praxis. Lasst uns auch blutig sein. Ich schreibe /\ (a :: k). t
, um die Abstraktion explizit zu machen, die forall
und f @ type
für die entsprechende Anwendung entspricht. Das Spiel ist, dass wir die @
-Argumente auswählen, aber wir müssen bereit sein, mit allem, was der Teufel wählen kann, fertig zu werden.
Wir haben
x :: forall (a :: *) (m :: * -> *). m a -> Int
und kann dementsprechend feststellen, dass f1 x
wirklich
f1 @ * (/\ (a :: *) (m :: * -> *). x @ a @ m)
jedoch ist, wenn wir versuchen, f2 x
die gleiche Behandlung zu geben, sehen wir
f2 (/\ (k :: BOX) (a :: k) (m :: k -> *). x @ ?m0 @ ?a0)
?m0 :: *
?a0 :: * -> *
where m a = m0 a0
Die Haskell-Typ-System behandelt Typ-Anwendung als rein syntaktisch, so dass der einzige Weg, kann diese Gleichung gelöst werden soll, indem die Funktionen zu identifizieren und zu identifizieren, die Argumente
(?m0 :: * -> *) = (m :: k -> *)
(?a0 :: *) = (a :: k)
aber diese Gleichungen sind nicht einmal gut kinded, weil k
nicht frei gewählt werden: es ist /\
-ed nicht @
-ed.
Um sich mit diesen überpolymorphen Typen vertraut zu machen, ist es gut, alle Quantifizierer auszugeben und dann herauszufinden, wie sich das zum Spiel gegen den Teufel entwickelt. Wer wählt was und in welcher Reihenfolge. Das Verschieben eines forall
innerhalb eines Argumenttyps ändert seine Auswahl und kann oft den Unterschied zwischen Sieg und Niederlage ausmachen.
Was genau ist 'k' dort? Ist 'k' variabel für eine spezielle Sache wie' * '? – Sibi
@Sibi 'k' ist eine Art Variable,' * 'ist einer seiner möglichen" Werte ". In Haskell-Typen haben Arten ähnlich wie Werte Typen, obwohl Sie Erweiterungen benötigen, um mehr als die eingebauten festen Arten wie '*' und '* -> *' zu verwenden. –