Diferença entre polimorfismo de linha e polimorfismo limitado?

7

Recentemente, deparei-me com este post de Brian McKenna explicando o polimorfismo de linha. Pareceu-me uma ideia maravilhosa, mas então percebi que cheira muito a polimorfismo paramétrico limitado:

Com polimorfismo de linha:

sum: {x: int, y: int | rho} -> int
function sum r = r.x + r.y

Com polimorfismo paramétrico limitado:

sum: forall a <: {x: int, y: int}. a -> int
function sum r = r.x + r.y

Alguém pode esclarecer as diferenças de polimorfismo entre essas duas abordagens?

Gardenhead
fonte
2
Você já tentou digitar let f x = x with {sum: x.a + x.b}com os dois? Se bem entendi, o polimorfismo de linha permitirá que você mantenha quaisquer campos extras no xpolimorfismo paramétrico limitado, mas não porque você quer dizer que é do tipo forall a <: {x: int, y: int}. a -> a_with_a_new_field_sume acho que não pode expressar a_with_a_new_field_sum.
xavierm02
Hum, acho que depende dessa semântica exata da withconstrução. Como isso não foi apresentado no artigo, tentei evitá-lo, porque confunde as coisas.
precisa saber é o seguinte
11
Bem (acho que) a expressividade do polimorfismo de linha vem do fato de você ter um nome para "e vários outros atributos". Portanto, se você não usar a variável type que representa esse monte de outros atributos na digitação de sua função, provavelmente não precisará realmente de polimorfismo de linha. Você também pode ter algum forgetoperador que registre e remova um de seus campos. Então, para digitar fun r -> forget x of r, você provavelmente também precisará de polimorfismo de linha.
precisa saber é
Sem mais detalhes sobre os sistemas, eu diria que eles são equivalentes, exceto, é claro, que o polimorfismo limitado é mais geral. Normalmente, a digitação de linha também implica algumas operações em nível de tipo em linhas como união ou restrição de linha. Eu digo coisas semelhantes nesta resposta .
Derek Elkins saiu de SE

Respostas:

3

Portanto, existem algumas diferenças:

  • No polimorfismo de linha, você vincula a um nome para poder usá-lo em outro lugar. Por exemplo, é expressável com polimorfismo de linha, mas não puramente usando polimorfismo limitado. Da mesma forma, você pode até expressar a exclusão do campo desta maneira: é um tipo polimórfico de linha perfeitamente válido, mas a subtipagem não tem realmente uma maneira de expressar isso.ρforall rho . rho -> {x : int | rho}forall rho .{x : int | rho} -> rho

    Como o polimorfismo de linha permite adicionar e excluir campos dessa maneira, normalmente ele funciona com uma semântica de "pilha", para que os campos antigos sejam sombreados quando novos campos com o mesmo nome são adicionados.

  • Subtipagem limitada usa, bem, subtipagem. Portanto, com o polimorfismo de linha, você não pode dar x : {x : int, y : int}como argumento uma função do tipo {x : int} ->int. Mas a maioria dos sistemas com subtipo limitado também teria subtipo não polimórfico, o que permitiria isso, já que a maioria dos sistemas possui {x : int} <: {x : int, y : int}.

A subtipagem limitada tende a ser um pouco mais precisa e flexível, e a semântica de "pilha" do polimorfismo de linha não ocorre muito. Mas a inferência é muito mais fácil para o polimorfismo de linha e pode funcionar na ausência de qualquer anotação de tipo (por exemplo, no Elm ), o que geralmente não é o caso na presença de subtipagem.

jmite
fonte