Registros simples correspondem a mapas do tipo dependente (e ainda não temos uma operação de mesclagem). Mais precisamente, o tipo de registro
{ lbl1 : A1, lbl2 : A2, ..., lblN : AN }
corresponde ao tipo de produto
∏ (ℓ : label), A ℓ
onde label
é o tipo de soma
lbl1 + lbl2 + ... + lblN
e A : label → Type
é a família de tipos definida por
A lbl1 ≡ A1
A lbl2 ≡ A2
⋮
A lblN ≡ AN
O tipo de registro acima também é equivalente ao produto simples
A1 × A2 × ⋯ × AN.
Você perguntou sobre registros extensíveis. Existem pelo menos duas maneiras de fazer isso. Sem nenhuma tecnologia adicional, podemos modelar uma extensão de
{ foo : A, bar : B } ≤ { foo : A, bar : B, baz C }
com algumas funções que mapeiam entre elas (projeção em uma direção e extensão por um campo extra na outra). Tudo isso é muito mundano.
Também poderíamos pedir o tipo de todos os tipos de registro possíveis. Suponha que tenhamos um tipo label
de todos os rótulos possíveis (na prática, poderia ser string
ou algo parecido). O tipo de todos os tipos de registro é
record ≡ label → option Type
Um elemento R : record
é um mapeamento de rótulos para tipos opcionais, onde
R lbl
assume valor None
se o rótulo lbl
não aparece R
e valor Some A
se ele aparece e tem tipo A
.
Se, R : record
então, o tipo descrito por R
é o tipo de produto
∏ (ℓ : label),
match R ℓ with
| Some A ⇒ A
| None ⇒ unit
end
Isso significa que um registro r
do tipo R
é uma função dependente que leva um rótulo ℓ
a um elemento de A
se ℓ
aparecer na R
unidade e de outra forma.
No entanto, uma merge
operação é problemática, bem como uma relação de subtipagem R ≤ Q
. Isso ocorre porque não podemos expressar o fato de que uma gravadora lbl
tem o mesmo tipo de registro R
e registro Q
. Na melhor das hipóteses, você pode dizer que os tipos são isomórficos ou proposicionalmente iguais, mas não é isso que você deseja.
Nós podemos definir uma extend
operação
extend : record → record → record
em que o primeiro argumento substitui o segundo, para que extend R Q
os campos R
adicionalmente Q
não sejam exibidos em R
:
extend R Q ≡
λ (ℓ : label),
match Q ℓ with
| Some A ⇒ Some A
| None ⇒ Q ℓ
end