↑Programmieren in Gallina
Zum Einstieg wurde bereits erklärt, wie sich mit Inductive
neue Typen definieren lassen. Eigentlich handelt es sich bei der
Konstruktion induktiver Typen um ein recht komplexes Werkzeug, etwas
was man als eierlegende Wollmilchsau bezeichnen würde. Es enthält
drei verschiedene Teilaspekte:
newtype
in Haskell
oder enum
, struct
in Rust.
Zum ersten Teilaspekt legen wir Typen A
und
B
derselben Struktur fest.
Inductive A := cons_A (n: nat). Inductive B := cons_B (n: nat). Definition a := cons_A 0. Check a: A.
Wäre die Typisierung von A
, B
strukturell, so würde Check a: B
ebenfalls
aufgehen. Der Typprüfer gibt uns jedoch zu verstehen, dass dies nicht
stimmt. Sollen A
, B
tatsächlich
strukturell typisiert sein, müsste man sie vermittels
Definition
als Typalias zu nat
festlegen.
Definition A := nat. Definition B := nat. Definition a: A := 0. Check a: B.
Man stellt weiterhin fest, dass als Record
definierte
Typen allem Anschein nach bereits nominal typisiert sind. Wir testen
dies kurzerhand am Beispiel
Record PointA := {Ax: nat; Ay: nat}. Record PointB := {Bx: nat; By: nat}. Definition a := {|Ax := 0; Ay := 0|}. Check a: PointA.
aus. Läge strukturelle Typisierung vor, würde
Check a: PointB
aufgehen. Es tut sich die
Frage auf, ob Strukturen mit benannten Feldern bzw. Projektionen
überhaupt definierbar sind. Zuweilen betrifft dies auch andere
Sprachen. So tat man sich bei Rust schwer, structural
records zur Sprache hinzuzufügen; bisweilen sind sie nur emulierbar.
Sie sind aus ergonomischen Gründen wünschenswert, dergestalt dass damit
Funktionen mit benannten Argumenten erklärt werden können.
In Gallina bekommen wir benannte Argumente elegant als Winkelzug
via Typinferenz auf Basis der Projektionen. Betrachten wir dazu die
folgende quadratische Form sq
mit den benannten Argumenten
x
und y
.
Record Point := {x: nat; y: nat}. Definition sq (a: Point) := 3*a.(x)*a.(x) + 2*a.(y)*a.(y). Compute sq {|x := 1; y := 2|}.
Eine Struktur lässt sich sogar per Musterabgleich auflösen, wie
Definition sq '(Build_Point x y) := 3*x*x + 2*y*y.
zeigt. Man darf dies allerdings als bedenklich erachten, weil es nun, da die Projektionen vom selben Typ sind, auf die Reihenfolge ankommt.