Okay, lass uns eins nach dem anderen gehen.
Werte
Werte sind die konkreten Daten, die Programme auswerten und jonglieren. Nichts Besonderes, vielleicht einige Beispiele
1
true
"fizz buzz foo bar"
Typen
Eine schöne Beschreibung für einen Typ ist "ein Klassifikator für einen Wert". Ein Typ ist eine kleine Information darüber, was dieser Wert zur Laufzeit sein wird, wird aber zur Kompilierungszeit angezeigt.
Wenn Sie mir zum Beispiel sagen, dass dies e : bool
zur Kompilierungszeit der Fall ist und ich weiß, dass dies e
entweder true
oder zur false
Laufzeit der Fall ist, gibt es sonst nichts! Da Typen Werte wie folgt klassifizieren, können wir diese Informationen verwenden, um einige grundlegende Eigenschaften Ihres Programms zu bestimmen.
Wenn ich zum Beispiel jemals sehe, dass Sie etwas hinzufügen e
und e'
wann e : int
und e' : String
, dann weiß ich, dass etwas nicht stimmt! Tatsächlich kann ich dies markieren und beim Kompilieren einen Fehler auslösen und sagen "Hey, das ergibt überhaupt keinen Sinn!".
Ein leistungsfähigeres Typensystem ermöglicht interessantere Typen, die interessantere Werte klassifizieren. Betrachten wir zum Beispiel eine Funktion
f = fun x -> x
Es ist ziemlich klar f : Something -> Something
, aber was soll das Something
sein? In einem langweiligen Typensystem müssten wir etwas Beliebiges wie spezifizieren Something = int
. In einem flexibleren Typensystem könnte man sagen
f : forall a. a -> a
Das heißt "für jeden a
, f
ordnet an an a
zu a
". Dies wollen wir f
allgemeiner verwenden und interessantere Programme schreiben.
Außerdem prüft der Compiler, ob der von uns angegebene Klassifikator tatsächlich erfüllt ist, wenn f = fun x -> true
dann ein Fehler vorliegt und der Compiler dies sagt!
Also als tldr; Ein Typ ist eine Zeitbeschränkung für die Kompilierung der Werte, die ein Ausdruck zur Laufzeit haben kann.
Geben Sie Konstruktor ein
Einige Typen sind verwandt. Eine Liste von Ganzzahlen ist beispielsweise einer Liste von Zeichenfolgen sehr ähnlich. Dies ist fast so, wie es sort
bei ganzen Zahlen sort
bei Strings der Fall ist . Wir können uns eine Art Fabrik vorstellen, die diese fast gleichen Typen baut, indem wir ihre Unterschiede verallgemeinern und sie nach Bedarf bauen. Das ist was ein Typkonstruktor ist. Es ist wie eine Funktion von Typ zu Typ, aber etwas eingeschränkter.
Das klassische Beispiel ist eine generische Liste. Ein Typkonstruktor für ist nur die generische Definition
data List a = Cons a (List a) | Nil
Jetzt List
gibt es eine Funktion, die einen Typ a
einer Liste von Werten dieses Typs zuordnet! In Java-Land werden diese vielleicht "generische Klassen" genannt.
Geben Sie Parameter ein
Ein Typparameter ist nur der Typ, der an einen Typkonstruktor (oder eine Funktion) übergeben wird. Genau wie in der Wertebene haben wir foo(a)
einen Parameter, a
genauso wie List a
ein Typparameter a
.
Arten
Arten sind ein bisschen schwierig. Die Grundidee ist, dass bestimmte Typen ähnlich sind. Zum Beispiel haben wir alle primitiven Typen in Java int
, char
, float
... die alle verhalten sich , als ob sie die gleiche „Art“ haben. Wenn wir jedoch von den Klassifizierern für Typen selbst sprechen, nennen wir die Klassifizierertypen. Also int : Prim
, String : Box
, List : Boxed -> Boxed
.
Dieses System gibt schöne konkrete Regeln darüber, welche Arten von Typen wir wo verwenden können, genau wie Typen Werte regeln. Es wäre eindeutig Unsinn zu sagen
List<List>
oder
List<int>
In Java muss da List
auf einen konkreten Typ angewendet werden, um so verwendet zu werden! Wenn wir uns ihre Arten ansehen List : Boxed -> Boxed
und da Boxed -> Boxed /= Boxed
, ist das obige ein freundlicher Fehler!
Die meiste Zeit denken wir nicht wirklich über Arten nach und behandeln sie nur als "gesunden Menschenverstand", aber bei schickeren Typsystemen ist es wichtig, darüber nachzudenken.
Eine kleine Illustration dessen, was ich bisher gesagt habe
value : type : kind : ...
true : bool : Prim : ...
new F() : Foo : Boxed : ...
Besser lesen als Wikipedia
Wenn Sie sich für so etwas interessieren, würde ich Ihnen wärmstens empfehlen, ein gutes Lehrbuch anzulegen. Typentheorie und PLT im Allgemeinen sind ziemlich umfangreich und ohne eine zusammenhängende Wissensbasis können Sie (oder zumindest ich) herumirren, ohne monatelang irgendwo hin zu kommen.
Zwei meiner Lieblingsbücher sind
- Typen und Programmiersprache - Ben Pierce
- Praktische Grundlagen von Programmiersprachen - Bob Harper
Beide sind ausgezeichnete Bücher, die das, worüber ich gerade gesprochen habe, und vieles mehr in schönen, gut erklärten Details vorstellen.