Einfache Datensätze entsprechen Karten vom abhängigen Typ (und wir haben noch keine Zusammenführungsoperation). Genauer gesagt, der Datensatztyp
{ lbl1 : A1, lbl2 : A2, ..., lblN : AN }
entspricht dem Produkttyp
∏ (ℓ : label), A ℓ
Wo label
ist der Summentyp?
lbl1 + lbl2 + ... + lblN
und A : label → Type
ist die Typfamilie definiert durch
A lbl1 ≡ A1
A lbl2 ≡ A2
⋮
A lblN ≡ AN
Der obige Datensatztyp entspricht auch dem einfachen Produkt
A1 × A2 × ⋯ × AN.
Sie haben nach erweiterbaren Datensätzen gefragt. Es gibt mindestens zwei Möglichkeiten, dies zu tun. Ohne zusätzliche Technologie können wir eine Erweiterung von modellieren
{ foo : A, bar : B } ≤ { foo : A, bar : B, baz C }
mit ein paar Funktionen, die zwischen ihnen abgebildet werden (Projektion in eine Richtung und Erweiterung um ein zusätzliches Feld in der anderen). Das ist alles sehr banal.
Wir könnten auch nach dem Typ aller möglichen Datensatztypen fragen. Angenommen, wir haben eine Art label
aller möglichen Etiketten (in der Praxis könnte es sein string
oder so). Der Typ aller Datensatztypen ist
record ≡ label → option Type
Ein Element R : record
ist eine Zuordnung von Beschriftungen zu optionalen Typen, wobei
R lbl
Wert verwendet wird, None
wenn Beschriftung lbl
nicht in angezeigt wird, und R
Wert, Some A
wenn sie angezeigt wird und Typ hat A
.
Wenn R : record
dann der beschriebene Typ der Produkttyp R
ist
∏ (ℓ : label),
match R ℓ with
| Some A ⇒ A
| None ⇒ unit
end
Dies bedeutet, dass ein Datensatz r
vom Typ R
eine abhängige Funktion ist, die eine Beschriftung ℓ
für ein Element von A
if ℓ
in R
und für die Einheit andernfalls verwendet.
Eine merge
Operation ist jedoch problematisch, ebenso wie eine Subtypisierungsbeziehung R ≤ Q
. Dies liegt daran, dass wir nicht ausdrücken können, dass ein Label lbl
in Datensatz R
und Datensatz denselben Typ hat Q
. Bestenfalls kann man sagen, dass die Typen isomorph oder aussagekräftig sind, aber das ist nicht das, was Sie wollen.
Wir können eine extend
Operation definieren
extend : record → record → record
in dem das erste Argument das zweite überschreibt, so dass extend R Q
die Felder von R
zusätzlich die Felder davon Q
nicht erscheinen in R
:
extend R Q ≡
λ (ℓ : label),
match Q ℓ with
| Some A ⇒ Some A
| None ⇒ Q ℓ
end