Im Internet finden Sie Folgendes:
Höher sortierter Typ == Typ Konstruktor?
class AClass[T]{...} // For example, class List[T]
Einige sagen, dies sei ein höherwertiger Typ, da er über Typen abstrahiert, die der Definition entsprechen würden.
Höher sortierte Typen sind Typen, die andere Typen annehmen und einen neuen Typ erstellen
Diese werden jedoch auch als Typkonstruktor bezeichnet . (Zum Beispiel in Programmieren in Scala ).
Höher sortierter Typ == Typkonstruktor, der den Typkonstruktor als Typparameter verwendet?
In der Zeitung Generika höherer Art können Sie lesen
... Typen, die über Typen abstrahieren, die über Typen abstrahieren ('Typen höherer Art') ... "
was darauf hindeutet
class XClass[M[T]]{...} // or trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]]
ist ein höherwertiger Typ.
Also in diesem Sinne ist es schwierig , zu unterscheiden zwischen Typkonstruktor , höherer kinded Art und Typkonstruktor der Typkonstruktoren als Typ - Parameter nimmt daher die Frage oben.
Antworten:
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.
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:
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 TypString
, 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:
"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:
Wo die verwendeten Klassen definiert wurden als:
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:
(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}
)quelle
(Diese Antwort ist ein Versuch, die Antwort von Adriaan Moors mit einigen grafischen und historischen Informationen zu dekorieren.)
Höher sortierte Typen sind seit 2.5 Teil von Scala.
Zuvor erlaubte Scala als Java bisher nicht, den Typkonstruktor ("Generika" in Java) als Typparameter für einen Typkonstruktor zu verwenden. z.B
war nicht möglich.
(Bild von Generika höherer Art abgeleitet )
Die Konsequenz ist, dass der Typkonstruktor (z. B.
List
) genauso wie andere Typen in der Position der Typparameter von Typkonstruktoren verwendet werden kann und daher seit Scala 2.5 zu erstklassigen Typen wird. (Ähnlich wie Funktionen, die in Scala erstklassige Werte sind).Im Kontext eines Typsystems, das höhere Arten unterstützt, können wir geeignete Typen , Typen wie
Int
oderList[Int]
von Typen erster Ordnung wieList
und Typen höherer Art wieFunctor
oderMonad
(Typen, die über Typen abstrahieren, die über Typen abstrahieren) unterscheiden.Das Typsystem von Java auf der anderen Seite unterstützt keine Arten und hat daher keine Typen einer "höheren Art".
Dies muss also vor dem Hintergrund des unterstützenden Typsystems gesehen werden.
Im Fall von Scala sehen Sie häufig Beispiele für einen Typkonstruktor wie
mit der Überschrift "Höher sortierte Typen", zB in Scala für generische Programmierer, Abschnitt 4.3
Dies ist manchmal irreführend, weil viele
Container
als höherwertiger Typ bezeichnen und nichtIterable
, aber was genauer ist, ist:quelle
Die Art von gewöhnlichen Typen wie
Int
undChar
, deren Instanzen Werte sind, ist*
. Die Art von unären Typkonstruktoren wieMaybe
ist* -> *
; Konstruktoren vom binären Typ wieEither
haben ( Curry- ) Art* -> * -> *
und so weiter. Sie können Typen wieMaybe
und anzeigenEither
als Funktionen auf : Sie nehmen einen oder mehrere Typen an und geben einen Typ zurück.Eine Funktion ist höherer Ordnung, wenn sie eine Ordnung größer als 1 hat, wobei die Reihenfolge (informell) die Verschachtelungstiefe der Funktionspfeile links ist:
1 :: Int
chr :: Int -> Char
fix :: (a -> a) -> a
,map :: (a -> b) -> [a] -> [b]
((A -> B) -> C) -> D
(((A -> B) -> C) -> D) -> E
Kurz gesagt, ein Typ höherer Ordnung ist nur eine Funktion höherer Ordnung auf Typebene .
Int :: *
Maybe :: * -> *
Functor :: (* -> *) -> Constraint
- höherwertig: Konvertiert unäre Typkonstruktoren in Typklasseneinschränkungenquelle
Functor
Erzeugt einen richtigen Typ ( naja , Merkmal, aber die gleiche Idee)Functor[F[_]]
aus einem TypkonstruktorF
.(* => *) => (* => *)
Typkonverter in Scala ausgedrückt werden? Wenn nicht, in einer anderen Sprache?* ⇒ * ⇒ *
mit Curry ist sehr hilfreich. Vielen Dank!(* ⇒ *) ⇒ (* ⇒ *)
kann auch geschrieben werden(* ⇒ *) ⇒ * ⇒ *
. Es kann in Scala wie ausgedrückt werdenFoo[F[_], T]
. Dies ist die Art eines Typs wie (in Haskell)newtype Twice f a = Twice (f (f a))
(z. B.Twice Maybe Int
≅Maybe (Maybe Int)
,Twice [] Char
≅[[Char]]
) oder etwas Interessanteres wie die freie Monadedata Free f a = Pure a | Free (f (Free f a))
.Ich würde sagen: Ein höherwertiger Typ abstrahiert über einen Typkonstruktor . ZB überlegen
Hier
Functor
ist ein "höherwertiger Typ" (wie er im "Generics of a Higher Kind" -Papier verwendet wird ). Es ist kein konkreter Konstruktor vom Typ "erster Ordnung"List
(der nur über die richtigen Typen abstrahiert). Es abstrahiert über alle unären Konstruktoren ("erster Ordnung") (wie mit bezeichnetF[_]
).Oder
List<T>
anders ausgedrückt: In Java haben wir eindeutig Typkonstruktoren (z. B. ), aber wir haben keine "höher sortierten Typen", weil wir nicht über sie abstrahieren können (z. B. können wirFunctor
die oben definierte Schnittstelle nicht schreiben - zumindest nicht direkt ).Der Begriff "Polymorphismus höherer Ordnung (Typkonstruktor)" wird verwendet, um Systeme zu beschreiben, die "Typen höherer Ordnung" unterstützen.
quelle
List<T>
wäre Java ein unärer Typkonstruktor, da es eindeutig die Art hat* -> *
. Was in Jons Antwort fehlt, ist, dass Sie in der Lage sein müssen, über das "Ganze" (und nicht nur über das zweite*
wie in Java) zu abstrahieren , um es einen höherwertigen Typ zu nennen.def succ(x: Int) = x+1
führt den "Wertekonstruktor" ein (siehe meine andere Antwort für das, was ich damit meine)succ
(niemand würde diesen Wert als succ (x: Int) bezeichnen). In Analogie dazuFunctor
ist der (in der Tat höherwertige) Typ in Ihrer Antwort definiert. Auch hier sollten Sie es nicht alsFunctor[F[_]]
(was istF
? Was ist_
? Sie sind nicht im Geltungsbereich! Leider trübt der syntaktische Zucker für Existenziale das Wasser hier, indem erF[_]
kurz machtF[T forSome {type T}]
) bezeichnenScala REPL bietet
:kind
Befehl, derZum Beispiel,
Das
:help
enthält klare Definitionen, daher denke ich, dass es sich lohnt, es hier in seiner Gesamtheit zu veröffentlichen (Scala 2.13.2).quelle