Lassen Sie mich etwas von dieser Verwirrung wettmachen, indem ich mit einer gewissen Begriffsklärung einspringe. Ich verwende gerne die Analogie zur Wertebene, um dies zu erklären, da die Leute eher damit vertraut sind.
Ein Typkonstruktor ist ein Typ, den Sie auf Typargumente anwenden können, um einen Typ zu "konstruieren".
Ein Wertekonstruktor ist ein Wert, den Sie auf Wertargumente anwenden können, um einen Wert zu "konstruieren".
Wertekonstruktoren werden normalerweise als "Funktionen" oder "Methoden" bezeichnet. Diese "Konstruktoren" werden auch als "polymorph" (weil sie verwendet werden können, um "Zeug" unterschiedlicher "Form" zu konstruieren) oder "Abstraktionen" (da sie über das abstrahieren, was zwischen verschiedenen polymorphen Instanziierungen variiert) bezeichnet.
Im Kontext von Abstraktion / Polymorphismus bezieht sich erste Ordnung auf die "einmalige Verwendung" von Abstraktion: Sie abstrahieren einmal über einen Typ, aber dieser Typ selbst kann nicht über irgendetwas abstrahieren. Java 5-Generika sind erster Ordnung.
Die Interpretation der obigen Charakterisierungen von Abstraktionen erster Ordnung ist:
Ein Typkonstruktor ist ein Typ, den Sie auf geeignete Typargumente anwenden können, um einen geeigneten Typ zu "konstruieren".
Ein Wertekonstruktor ist ein Wert, den Sie auf geeignete Wertargumente anwenden können, um einen geeigneten Wert zu "konstruieren".
Um zu betonen, dass es sich nicht um eine Abstraktion handelt (ich denke, Sie könnten dies als "nullter Ordnung" bezeichnen, aber ich habe nicht gesehen, dass dies irgendwo verwendet wird), wie zum Beispiel den Wert 1
oder den Typ String
, sagen wir normalerweise, dass etwas ein "richtiger" Wert oder Typ ist.
Ein geeigneter Wert ist "sofort verwendbar" in dem Sinne, dass er nicht auf Argumente wartet (er abstrahiert nicht über sie). Stellen Sie sich diese als Werte vor, die Sie leicht drucken / überprüfen können (das Serialisieren einer Funktion ist Betrug!).
Ein richtiger Typ ist ein Typ, der Werte klassifiziert (einschließlich Wertekonstruktoren). Typkonstruktoren klassifizieren keine Werte (sie müssen zuerst auf die richtigen Typargumente angewendet werden, um einen richtigen Typ zu erhalten). Um einen Typ zu instanziieren, ist es notwendig (aber nicht ausreichend), dass es sich um einen richtigen Typ handelt. (Es kann sich um eine abstrakte Klasse handeln oder um eine Klasse, auf die Sie keinen Zugriff haben.)
"Höhere Ordnung" ist einfach ein Oberbegriff, der die wiederholte Verwendung von Polymorphismus / Abstraktion bedeutet. Dies gilt auch für polymorphe Typen und Werte. Konkret abstrahiert eine Abstraktion höherer Ordnung über etwas, das über etwas abstrahiert. Für Typen ist der Begriff "höherwertig" eine Spezialversion der allgemeineren "übergeordneten Ordnung".
Somit wird die übergeordnete Version unserer Charakterisierung:
Ein Typkonstruktor ist ein Typ, den Sie auf Typargumente (richtige Typen oder Typkonstruktoren) anwenden können, um einen richtigen Typ (Konstruktor) zu "konstruieren".
Ein Wertekonstruktor ist ein Wert, den Sie auf Wertargumente (Eigenwerte oder Wertekonstruktoren) anwenden können, um einen Eigenwert (Konstruktor) zu "konstruieren".
"Höhere Ordnung" bedeutet also einfach, dass Sie es wirklich meinen, wenn Sie "über X abstrahieren" sagen! Das X
, über das abstrahiert wird, verliert nicht seine eigenen "Abstraktionsrechte": Es kann alles abstrahieren, was es will. (Übrigens verwende ich hier das Verb "abstrakt", um zu bedeuten: etwas wegzulassen, das für die Definition eines Wertes oder Typs nicht wesentlich ist, damit es vom Benutzer der Abstraktion als Argument variiert / bereitgestellt werden kann .)
Hier sind einige Beispiele (inspiriert von Lutz 'Fragen per E-Mail) für richtige Werte und Typen erster und höherer Ordnung:
proper first-order higher-order
values 10 (x: Int) => x (f: (Int => Int)) => f(10)
types (classes) String List Functor
types String ({type λ[x] = x})#λ ({type λ[F[x]] = F[String]})#λ
Wo die verwendeten Klassen definiert wurden als:
class String
class List[T]
class Functor[F[_]]
Um die Indirektion durch das Definieren von Klassen zu vermeiden, müssen Sie anonyme Typfunktionen ausdrücken, die in Scala nicht direkt ausgedrückt werden können. Sie können jedoch Strukturtypen ohne zu großen syntaktischen Aufwand verwenden (der #λ
Stil ist auf https://stackoverflow.com zurückzuführen / users / 160378 / retronym afaik):
In einer hypothetischen zukünftigen Version von Scala, die anonyme Typfunktionen unterstützt, können Sie diese letzte Zeile aus den Beispielen auf Folgendes verkürzen:
types (informally) String [x] => x [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be
(Persönlich bedauere ich, dass ich jemals über "höherwertige Typen" gesprochen habe, sie sind schließlich nur Typen! Wenn Sie unbedingt unterscheiden müssen, schlage ich vor, Dinge wie "Typkonstruktorparameter", "Typkonstruktormitglied" zu sagen. oder "Typkonstruktor-Alias", um zu betonen, dass es sich nicht nur um richtige Typen handelt.)
ps: Um die Sache noch weiter zu verkomplizieren, ist "polymorph" auf andere Weise mehrdeutig, da ein polymorpher Typ manchmal einen universell quantifizierten Typ bedeutet, z. B. Forall T, T => T
einen geeigneten Typ, da er polymorphe Werte klassifiziert (in Scala kann dieser Wert sein geschrieben als Strukturtyp {def apply[T](x: T): T = x}
)