2017-02-08 4 views
2

Ich habe über abhängige Typen gelesen und ich habe eine Frage, um sicherzustellen, dass ich nicht etwas falsch verstehe. Die Wikipedia page on dependent types startet damit:Sind durch Werte parametrisierte Generika die gleichen wie abhängige Typen?

In der Informatik und Logik ist ein abhängiger Typ ein Typ, dessen Definition von einem Wert abhängt. Ein "Paar Ganzzahlen" ist ein Typ. Ein "Paar von ganzen Zahlen, wobei die zweite größer als die erste ist" ist aufgrund der Abhängigkeit von dem Wert ein abhängiger Typ.


glaube, ich habe eine Sprache, wo ich eine Zahl in einem Bereich darstellen kann:

struct Int<Min, Max> 

beispielsweise der Typ Int<0, 10> eine ganze Zahl zwischen 0 und einschließlich 10 exklusiv.

Als Bonus, nehme ich an generische Varianz vorstellen:

struct Int<in Min, out Max> 

Zum Beispiel Instanzen von Typen wie Int<3, 10> und Int<0, 8> können Variablen von Int<0, 10> Typ zugeordnet werden.

Int<Min1 + Min2, Max1 + Max2> operator+(Int<Min1, Max1> op1, Int<Min2, Max2> op2); 

Also, das Hinzufügen eines Int<0, 10> und ein erzeugen würde ein Ergebnis vom Typ Int<3, 14>:

Nun ist die Additionsoperation auf diese Art eine Signatur wie diese haben könnte.

In einem solchen Typ-System, konnten wir auch bestellt haben Paare, wie zB:

struct OrderedPair<Min, Mid, Max> 
{ 
    Int<Min, Mid> SmallerNumber; 
    Int<Mid, Max> LargerNumber; 
} 

Und so weiter.


Ist das anders als abhängige Typisierung? Wenn das so ist, wie?

+0

Ein abhängiger Typ ermöglicht es Ihnen, ein Prädikat an einen Typ anzuhängen und zu überprüfen, ob es in allen Operationen gültig ist. Wenn Sie Ihr System auf einige Prädikate beschränken können (z. B. min/max für einen Bereich), können Sie es zu einem gewissen Grad auslagern, um Parameter einzugeben. Haskell erlaubt das irgendwie, habe ich gehört. Das heißt, für einen praktischen Fall von Zahlen innerhalb eines Bereichs oder von Listen mit nicht mehr als N Elementen können Sie dies wahrscheinlich erreichen.Im Allgemeinen wahrscheinlich nicht, warum würden Menschen dann abhängig typisierte Sprachen erfinden? – 9000

+1

@ 9000 Ja, ich versuche grundsätzlich zu verstehen, ob bestimmte Typen (wie diese "Int ", eine mögliche "Liste ", sowie einige andere) grundsätzlich als Bausteine ​​verwendet werden können, um zu einem Ganzen zu gelangen type System von abhängigen Typen, oder ein abhängiges System ist etwas ganz anderes. –

Antwort

3

Dies ist eine eingeschränkte Form der abhängigen Typisierung, bei der Typen von Werten abhängen können, die jedoch zum Zeitpunkt der Kompilierung verfügbar sein müssen.

In einer vollständig abhängigen typisierten Sprache wie Idris können Typen auch von Laufzeitwerten abhängen - um einen solchen Wert zu erstellen, benötigen Sie einen proof im Bereich, in dem der Wert den Typ bewohnt. Eine Möglichkeit, einen Beweis zu erhalten, ist mit einem einfachen Test (Pseudo-Code):

m = user_input(); 
n = user_input(); 

// Type error: n is not guaranteed to be in range. 
x = Int<0, m>(n); 

if (n >= 0 && n <= m) { 
    // Accepted: proofs of n >= 0 and n <= m in scope. 
    x = Int<0, m>(n); 
} 

So können Sie Ihr Beispiel in (sagen wir) C++ implementieren, sondern eine Int<Min, Max> Konstruktion erfordert eine dynamische Kontrolle im Konstruktor; Wenn C++ volle abhängige Typen hatte, konnte man nicht einmal den Konstruktor ohne irgendeine Form der Überprüfung (statisch oder dynamisch) aufrufen.

+0

Der Teil über den Beweis, der benötigt wird, um Instanzen zu erstellen, ist für mich sinnvoll. In diesem Code ist "m" jedoch ein Laufzeitwert. Es ist nicht nur, dass wir von "n" (ein unbeschränktes "int", vermutlich) zu einem "Int <0, m>", diesem Teil, den ich verstehe, gegangen sind. Aber 'Int <0, m>' enthält einen Wert, der statisch nicht bekannt ist. Kann die umschließende Funktion 'x' zurückgeben? Kann der Typ der umschließenden Funktion 'Int <0, m>' sein? Wenn dem so ist, wenn ich versuche, "Int <0, m>" zu "Int <0, 5>" zuzuordnen, woher weiß der Compiler, ob ich zu einem mehr oder weniger spezifischen Typ gehe? –

+0

Der Typ von 'x' in der if-Anweisung ist' Int <0, m>', aber der Typ der umschließenden Funktion kann nicht so sein, weil es nicht bekannt ist (nicht bewiesen werden kann), dass die Laufzeitwerte diese if-Prüfung bestehen . Wenn Sie jedoch eine else-Klausel haben, die "0" (oder "m") zurückgibt, können Sie daraus ableiten, dass der Rückgabetyp der gesamten Sache "Int <0, m>" lautet. – laughedelic

+0

@TheodorosChatzigiannakis: Ich denke, du könntest den Wert zurückgeben, indem du ihn in ein Existenzielles einwickelst, '∃m. Int <0, m> ', dann könnte der Aufrufer es entpacken, um lokal mit dem Wert von 'm' zu arbeiten. Das heißt, die Funktion sagt "Ich gebe einen Wert im Bereich [0, * m *] für einige * m *" zurück. Ein existentieller Typ wird in diesem Zusammenhang "abhängiges Paar" oder "Sigma-Typ" genannt, weil es ein Paar eines Wertes "m" und eines davon abhängigen Typs "Int <0, m>" ist. –

Verwandte Themen