8. Das Typsystem von PVS

Werbung
8. Das Typsystem von PVS
Zur Erinnerung: das Typsystem in PVS umfaßt
- vordefinierte Typen: bool, int usw.
- Deklaration von Typnamen für
- neue uninterpretierte Typen
- interpretierte Typen als Synonyme für Typen oder Typausdrücke
- Typausdrücke:
- Funktionstypen
- Tupel (kartesische Produkte)
- Abstrakte Datentypen
- Untertypen: für ein Prädikat p: [T -> bool]
- subt: TYPE = { x:T | p(x) }
- (p)
Maschinelles Beweisen mit PVS
8–1
Typen in PVS: Ergänzungen (1)
Typ-Deklarationen
- von Nichtleeren Typen: Deklaration mit TYPE+ oder NONEMPTY TYPE;
zum Nachweis der Nichtleerheit kann ein Element mit CONTAINING angegeben
werden:
nonzero int: NONEMPTY TYPE = {i: int | i /= 0 } CONTAINING 1
- von uninterpretierten Untertypen:
s : TYPE FROM t
Aufzählungstypen der Form
enum: TYPE = {e 1, ..., e n}
Die Namen e i müssen paarweise verschieden sein.
wirklich eine spezielle Form einer DATATYPE Spezifikation
; entsprechende Deklarationen und Axiome werden generiert
Maschinelles Beweisen mit PVS
8–2
Typen in PVS: Ergänzungen (2)
Record-Typen als weitere Typausdrücke:
[# a1 : t1, . . . an : tn #]
Die ti sind Typ-Ausdrücke, die ai die Bezeichner der Record-Felder.
Beispiel:
pair: TYPE = [# li, re: nat #]
Elemente von Record-Typen werden bezeichnet durch Ausdrücke der Form:
(# a1 := e1,..., an := en #)
Die Reihenfolge der Record-Elemente (Felder) muß nicht eingehalten werden; durch
die Feldnamen bleiben Record-Ausdrücke eindeutig.
Die Feldnamen werden zur Selektion von Record-Elementen verwendet mit spezieller
Syntax:
p: pair = (# li:=5, re:=3 #)
p’li ; 5
Maschinelles Beweisen mit PVS
8–3
Typen in PVS: Ergänzungen (3)
Typen können von Werten abhängen, d.h. parametrisiert sein.
Beispiele aus dem prelude:
m: VAR nat
upto(m): NONEMPTY TYPE = {n: nat | n <= m} CONTAINING m
below(m): TYPE = {n: nat | n < m}
auch mit mehreren Parametern:
i,j: VAR int
subrange(i, j): TYPE = {k: int | i <= k AND k <= j}
Ein subrange-Typ kann offensichtlich auch leer sein.
Maschinelles Beweisen mit PVS
8–4
Typen in PVS: Abhängige Typen
Ein Typ ist ein abhängiger Typ (engl. dependent types), wenn eine Komponente vom
Wert einer vorherigen Komponente abhängt.
Beispiel:
datum: TYPE = [# jj: jahr, mm: monat,
tt: {t: posnat | t <= tage(mm,jj) } #]
Der Typ der Tag-Komponente tt des Datums hängt von den Werten für das Jahr
und den Monat ab, hier ausgedrückt durch eine (geeignet definierte) Funktion tage.
Maschinelles Beweisen mit PVS
8–5
Abhängige Typen (2)
Beispiel aus dem prelude: Typ der endlichen Folgen (engl. finite sequences):
finite sequence: TYPE =
[# length: nat, seq: [below[length] -> T] #]
Operationen mit endlichen Folgen: z.B. Verkettung
o(fs1, fs2): finseq =
LET l1 = fs1‘length,
lsum = l1 + fs2‘length
IN (# length := lsum,
seq := (LAMBDA (n:below[lsum]):
IF n < l1
THEN fs1‘seq(n)
ELSE fs2‘seq(n-l1)
ENDIF) #);
Maschinelles Beweisen mit PVS
8–6
Abhängige Typen (3)
Abhängige Typen zur Verschärfung bzw. genaueren Spezifikation von Definitions- und
Wertebereich von Funktionen:
; Vermeidung von Partialität von Funktionen
nth(l:list[T], n: below(length(l))): RECURSIVE T =
IF n=0 THEN car(l)
ELSE nth(cdr(l), n-1)
ENDIF
MEASURE length(l)
Typüberprüfung stellt sicher, daß nicht versucht wird, auf nicht-existierende Listenelemente zuzugreifen.
; Einschränkung des Definitionsbereichs der Funktion nth
Maschinelles Beweisen mit PVS
8–7
Abhängige Typen (4)
mod: THEORY
i,k: VAR int
j: VAR nonzero_int
mod(i,j): { k | abs(k) < abs(j)} = ...
• Wertebereich ist eingeschränkt in dem Sinn, dass der Rumpf der Funktionsdefinition einen Wert bestimmen muß, der dem angegebenen Typ angehört.
• Bei Aufruf des Funktion mod wird dann garantiert, daß der Funktionswert angegebene Eigenschaft hat.
• Typinformation für mod bzw. einen Aufruf mod(i,j) kann dem Beweiser
übermittelt werden mit dem Kommando TYPEPRED.
Maschinelles Beweisen mit PVS
8–8
Abhängige Typen (5)
Prädikative Untertypen und abhängige Typen erlauben in gewissem Sinn die Spezifikation von Vor- und Nachbedingungen von Funktionen:
P (x , y) => Q(f (x , y), x , y)
Ohne abhängige Typen könnten P bzw. Q nur viel einfachere Typinformation enthalten (mehrstellige Prädikate ??)
Maschinelles Beweisen mit PVS
8–9
Abhängige Typen (6)
Beispiel: Realisierung der abstrakten Struktur stack durch Arrays und Größenindex
i,k: VAR int
...
istack: TYPE = [# size: nat, elems: [{n:nat | n < size} -> T]#]
ne istack: TYPE = {s1: istack | s1’size > 0 }
Operationen push und pop, Konstante empty für leeren Stack?
Maschinelles Beweisen mit PVS
8 – 10
Abhängige Typen (6a)
Beispiel: Realisierung der abstrakten Struktur stack durch Arrays und Größenindex
istack: TYPE = [# size: nat, elems: [{n:nat | n < size} -> T]#]
ne istack: TYPE = {s1: istack | s1’size > 0 }
push(e:T, s:istack): ne istack =
(# size := s’size + 1,
elems := (LAMBDA (j: below(s’size+1)):
IF j < s’size THEN s’elems(j)
ELSE e ENDIF) #)
pop(e:T, s:ne istack): istack =
(# size := s’size-1,
elems := (LAMBDA (j: below(s’size-1)): s’elems(j) #)
empty: istack =
(# size := 0, elems := (LAMBDA (j: nat | FALSE): 0) #)
Maschinelles Beweisen mit PVS
8 – 11
Typen in PVS: Judgements
Judgements dienen dazu, Typinformation, insbesondere diejenige, die mit prädikativen
Untertypen verbunden ist (semantische Typinformation) in einer Form zur Verfügung
zu stellen, die der Typechecker ausnutzen kann (“Hilfestellung” für den Typechecker).
; Anzahl zu generierenden TCCs kann (i.a.) reduziert werden
Judgements sind formalisierte Typ-Aussagen
- führen in der Regel zu TCCs, die nachgewiesen werden müssen
Formen von Judgements
• Constant Judgements: HAS TYPE
• Suntype Judgements: SUBTYPE OF
Maschinelles Beweisen mit PVS
8 – 12
Judgements – Beispiele (1)
mod: THEORY
i,k: VAR int
m: VAR posnat
n: VAR nat
j: VAR nonzero_int
mod(i,j): { k | abs(k) < abs(j)} = i - j+floor(i,j)
mod_below: JUDGEMENT mod(i,m) HAS TYPE below(m)
...
END mod
Maschinelles Beweisen mit PVS
8 – 13
Judgements – Beispiele (2)
i, j, k: VAR nat
n: VAR posnat
upfrom_nat_is_nat:
JUDGEMENT upfrom(i) SUBTYPE_OF nat
upfrom_posnat_is_posnat: JUDGEMENT upfrom(n) SUBTYPE_OF posnat
above_nat_is_posnat: JUDGEMENT above(i) SUBTYPE_OF posnat
subrange_nat_is_nat: JUDGEMENT subrange(i,j) SUBTYPE_OF nat
subrange_posnat_is_posnat: JUDGEMENT subrange(n,j) SUBTYPE_OF posnat
Maschinelles Beweisen mit PVS
8 – 14
Judgements – Beispiele (3)
injective?(f): bool = (FORALL x1, x2: (f(x1) = f(x2) => (x1 = x2)))
surjective?(f): bool = (FORALL y: (EXISTS x: f(x) = y))
bijective?(f): bool = injective?(f) & surjective?(f)
bij_is_inj: JUDGEMENT (bijective?) SUBTYPE_OF (injective?)
bij_is_surj: JUDGEMENT (bijective?) SUBTYPE_OF (surjective?)
bij is inj: JUDGEMENT (bijective?) SUBTYPE OF (injective?)
Maschinelles Beweisen mit PVS
8 – 15
Judgements – Beispiele (4)
orders [T: TYPE]: THEORY
BEGIN
x, y: VAR T
<=, < : VAR pred[[T, T]]
p: VAR pred[T]
preorder?(<=): bool = reflexive?(<=) & transitive?(<=)
preorder_is_reflexive: JUDGEMENT (preorder?) SUBTYPE_OF (reflexive?[T])
preorder_is_transitive: JUDGEMENT (preorder?) SUBTYPE_OF (transitive?[T])
equiv_is_preorder:
JUDGEMENT (equivalence?[T]) SUBTYPE_OF (preorder?)
partial_order?(<=): bool = preorder?(<=) & antisymmetric?(<=)
dichotomous?(<=): bool = (FORALL x, y: (x <= y OR y <= x))
total_order?(<=): bool = partial_order?(<=) & dichotomous?(<=)
total_is_po:
Maschinelles Beweisen mit PVS
JUDGEMENT (total_order?) SUBTYPE_OF (partial_order?)
8 – 16
Parametrisierte Theorien
Parametrisierung möglich mit
- Typen
- Konstanten (einschließlich Funktionskonstanten)
Theorie-Parameter ergeben zum Teil denselben Effekt wie polymorphe Typen
z.B. list[T] “polymorpher Typ” der Listen über einem beliebigen Elementtyp T
Streng genommen gibt es in PVS keine Typ-Variablen, d.h. in dem Sinn wie es
Variable für Grundobjekte, Funktionen, Prädikate usw. gibt
Keine Quantifizierung über Typen (das ist aber in komplexeren Typentheorien möglich
– z.B. Project Typelab der Abteilung)
Maschinelles Beweisen mit PVS
8 – 17
Herunterladen