gotchaMinor
Is there any difference between extensible records and dependent maps
Viewed 0 times
extensibleanyrecordsmapsdifferencebetweenandtheredependent
Problem
In a typed setting, records can be thought of as a map from field to type. If there is a well-typed record merge operation (which allows overlapping fields), is there any real difference between the resulting type and a dependent map in a dependently typed language?
Solution
Simple records correspond to maps of dependent type (and we don't have a merge operation yet). More precisely, the record type
corresponds to the product type
where
and
The record type above is also equivalent to the simple product
You asked about extensible records. There are at least two ways to do this. Without any additional technology we can model an extension of
with a couple of function that map between them (projection in one direction and extension by an extra field in the other). This is all very mundane.
We could also ask for the type of all possible record types. Suppose we have a type
An element
If
This means that a record
However, a
We can define an
in which the first argument overrides the second one so that
{ lbl1 : A1, lbl2 : A2, ..., lblN : AN }corresponds to the product type
∏ (ℓ : label), A ℓwhere
label is the sum typelbl1 + lbl2 + ... + lblNand
A : label → Type is the type family defined byA lbl1 ≡ A1
A lbl2 ≡ A2
⋮
A lblN ≡ ANThe record type above is also equivalent to the simple product
A1 × A2 × ⋯ × AN.You asked about extensible records. There are at least two ways to do this. Without any additional technology we can model an extension of
{ foo : A, bar : B } ≤ { foo : A, bar : B, baz C }with a couple of function that map between them (projection in one direction and extension by an extra field in the other). This is all very mundane.
We could also ask for the type of all possible record types. Suppose we have a type
label of all possible labels (in practice it could be string or some such). The type of all record types isrecord ≡ label → option TypeAn element
R : record is a mapping from labels to optional types, whereR lbl takes value None if label lbl does not appear in R and value Some A if it appears and have type A.If
R : record then the type decribed by R is the product type∏ (ℓ : label),
match R ℓ with
| Some A ⇒ A
| None ⇒ unit
endThis means that a record
r of type R is a dependent function which takes a label ℓ to an element of A if ℓ appears in R and to the unit otherwise.However, a
merge operation is problematic, as well as a subtyping relation R ≤ Q. This is so because we cannot express the fact that a label lbl has the same type in record R and record Q. At best you can say that the types are isomorphic, or propositionally equal, but that's not what you want.We can define an
extend operationextend : record → record → recordin which the first argument overrides the second one so that
extend R Q has the fields of R additionally those fields of Q that do not appear in R:extend R Q ≡
λ (ℓ : label),
match Q ℓ with
| Some A ⇒ Some A
| None ⇒ Q ℓ
endCode Snippets
{ lbl1 : A1, lbl2 : A2, ..., lblN : AN }∏ (ℓ : label), A ℓlbl1 + lbl2 + ... + lblNA lbl1 ≡ A1
A lbl2 ≡ A2
⋮
A lblN ≡ ANA1 × A2 × ⋯ × AN.Context
StackExchange Computer Science Q#59738, answer score: 6
Revisions (0)
No revisions yet.