Unterschied zwischen Reihenpolymorpismus und begrenztem Polymorpishmus?

7

Ich bin kürzlich auf diesen Blog-Beitrag von Brian McKenna gestoßen, der den Zeilenpolymorphismus erklärt. Das schien mir eine wundervolle Idee zu sein, aber dann wurde mir klar, dass es sehr nach begrenztem parametrischem Polymorphismus riecht:

Mit Zeilenpolymorphismus:

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

Mit begrenztem parametrischem Polymorphismus:

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

Kann jemand die Unterschiede zum Polymorphismus zwischen diesen beiden Ansätzen klären?

Gartenkopf
quelle
2
Haben Sie versucht, let f x = x with {sum: x.a + x.b}mit beiden zu tippen ? Wenn ich das richtig verstehe, können Sie mit dem Zeilenpolymorphismus alle zusätzlichen Felder im xbegrenzten parametrischen Polymorphismus beibehalten, da Sie sagen möchten, dass dies ein Typ ist, forall a <: {x: int, y: int}. a -> a_with_a_new_field_sumund ich glaube nicht, dass Sie dies ausdrücken können a_with_a_new_field_sum.
Xavierm02
Hm, ich denke es hängt von der genauen Semantik des withKonstrukts ab. Da dies im Artikel nicht dargelegt wurde, habe ich versucht, es zu vermeiden, weil es die Dinge verwirrt.
Gardenhead
1
Nun (ich denke das), die Ausdruckskraft des Zeilenpolymorphismus beruht auf der Tatsache, dass Sie einen Namen für "und eine Reihe anderer Attribute" erhalten. Wenn Sie also bei der Typisierung Ihrer Funktion nicht die Typvariable verwenden, die diese Reihe anderer Attribute darstellt, benötigen Sie wahrscheinlich keinen Zeilenpolymorphismus. Sie könnten auch einen forgetOperator haben, der einen Datensatz aufnimmt und eines seiner Felder entfernt. Zum fun r -> forget x of rTippen benötigen Sie wahrscheinlich auch Zeilenpolymorphismus.
Xavierm02
Ohne mehr Details über die Systeme würde ich sagen, dass sie ungefähr gleichwertig sind, außer natürlich, dass der begrenzte Polymorphismus allgemeiner ist. Normalerweise impliziert die Zeilentypisierung auch einige Operationen auf Textebene für Zeilen, z. B. Zeilenvereinigung oder Zeilenbeschränkung. Ich sage ähnliche Dinge in dieser Antwort .
Derek Elkins verließ SE

Antworten:

3

Es gibt also einige Unterschiede:

  • Beim Zeilenpolymorphismus haben Sie an einen Namen gebunden , sodass Sie ihn an anderer Stelle verwenden können. Zum Beispiel ist es mit Zeilenpolymorphismus ausdrückbar, aber nicht nur mit begrenztem Polymorphismus. Ebenso können Sie das Löschen von Feldern auf diese Weise ausdrücken : Dies ist ein vollkommen gültiger zeilenpolymorpher Typ, aber durch Subtypisierung kann dies nicht wirklich ausgedrückt werden.ρforall rho . rho -> {x : int | rho}forall rho .{x : int | rho} -> rho

    Da Sie mit Zeilenpolymorphismus auf diese Weise Felder hinzufügen und löschen können, funktioniert dies normalerweise mit einer "Stapel" -Semantik, sodass alte Felder beim Hinzufügen neuer gleichnamiger Felder schattiert werden.

  • Bei der begrenzten Untertypisierung wird die Untertypisierung verwendet. Mit Zeilenpolymorphismus können Sie also keine x : {x : int, y : int}Funktion vom Typ als Argument angeben {x : int} ->int. Aber die meisten Systeme mit begrenzter Subtypisierung hätten auch eine nicht polymorphe Subtypisierung, was dies ermöglichen würde, da die meisten Systeme dies getan haben {x : int} <: {x : int, y : int}.

Die begrenzte Untertypisierung ist tendenziell etwas präziser und flexibler, und die "Stapel" -Semantik des Zeilenpolymorphismus tritt nicht so häufig auf. Inferenz ist jedoch für den Zeilenpolymorphismus viel einfacher und kann ohne Typanmerkungen (z. B. in Elm ) funktionieren , was bei Subtypisierung normalerweise nicht der Fall ist.

jmite
quelle