Gibt es Programmiersprachen, mit denen Sie Arithmetik für Typen festlegen können?

9

Gibt es aus Neugier Sprachen, mit denen Sie Typen arithmetisch festlegen können, um neue Typen zu erstellen? So etwas wie:

interface A {
  void a();
  void b();
}

interface B {
  void b();
  void c();
}

interface C = A & B; // has b()
interface D = A | B; // has a(), b() and c()
interface E = (A & B) ^ B; // has c()

Ich weiß, dass diese Ideen in einigen Sprachen ausgedrückt werden können (dh Java hat List<Comparable & Serializable>für die Vereinigung der Schnittstellen), aber ich habe noch nie von einer Sprache gehört, die Typarithmetik unterstützt. Vielen Dank!

Haldean Brown
quelle
7
Wie wäre ein solcher Mechanismus nützlich?
Robert Harvey
4
Ein Muster, das ich oft gesehen habe, ist eine Schnittstelle, die zwei andere Schnittstellen erweitert und nichts hinzufügt (dh CanWriteAndCompare extends Serializable, Comparable {}), und ich habe darüber nachgedacht, wie ich dies verallgemeinern kann.
Haldean Brown
2
Außerdem bin ich heute auf einen Fall gestoßen, in dem ich eine Methode habe, die ein Aoder ein nehmen kann B, mit zwei Implementierungen, die genau gleich aussehen. In der Methode rufe ich eine polymorphe Methode auf, die ein Aoder ein annehmen kann B, daher sind die Implementierungen gleich, aber da ich zwei verschiedene Typen verwenden muss, benötige ich zwei Implementierungen. Das wäre einfacher, wenn ich es könnte myMethod(A | B aOrB).
Haldean Brown
1
OrOperation kann durch Mehrfachvererbung emuliert werden.
Benutzer

Antworten:

4

Tangente ( Spezifikation 0,3 ) verwendet etwas Ähnliches. (Haftungsausschluss: Dies ist mein eigenes kleines Forschungsprojekt)

Derzeit withfungiert er als Gewerkschaftsoperator, der die Vererbung modelliert, obwohl Pragmatismus sie nicht kommutativ gemacht hat. Sobald Sie Implementierungen in Methoden eingeführt haben, ist eine strikte Vereinigung gleichnamiger Methoden oft nicht das, was Sie wollen, und es ist sowieso unmöglich, sie richtig zu machen.

intersectEs wird unterstützt, dass Modelle Inferenzen für etwas eingeben, foo(T,T)bei dem die Parameter unterschiedlich sind.

Ergänzungen waren interessant, führten jedoch zu Teiltypen, deren korrekte Aufnahme nicht so nützlich und / oder mühsam schien - sie sind also nicht enthalten.

Ich weiß, dass es einige andere Forschungssprachen gibt, die mir begegnet sind und die etwas Ähnliches hatten, aber ich kann mich im Moment nicht an sie erinnern. Das Hauptproblem ist, dass die Dinge ohne strukturelle Typisierung nicht wirklich nützlich sind, was selbst nicht besonders beliebt ist. Das andere ist, dass Sie eine Art (Typ von Typen) benötigen, um den konstruierten Typ zu speichern, oder es ist nur eine Abkürzung für etwas, das ohne diese Fähigkeit nicht besonders idiomatisch ist. Und das ist weitaus seltener als strukturelles Tippen.

Es ist voreingenommen und es ist nicht viel, aber da ist es.

Telastyn
quelle
5

Ja, Ceylon ist eine Sprache mit Ad-hoc-Vereinigungs- und Kreuzungstypen, wie in diesem Kapitel der Ceylon-Tour beschrieben:

http://ceylon-lang.org/documentation/1.0/tour/types/

Es ist erstaunlich, wie viele coole Redewendungen man daraus macht. Hier ist ein interessantes Beispiel, das ich kürzlich gebloggt habe . Und hier ist eine kurze Präsentation, in der ich schnell einige einfache Redewendungen beschönige .

Noch besser ist, dass Vereinigungs- / Schnittpunkttypen das "fehlende Glied" sind, das die Inferenz generischer Typargumente in Ceylon wirklich richtig macht, im Gegensatz zu anderen Sprachen, die Subtyp und parametrischen Polymorphismus kombinieren.

Beachten Sie, dass diese Art der "Typarithmetik", wie Sie sie beschrieben haben, Einschränkungen unterliegt. Zum Beispiel können Sie keinen Set-Complement-Operator auf Typebene haben, zumindest nicht ohne Unentscheidbarkeit.

HTH

Gavin King
quelle
3

Scala unterstützt es teilweise (Schnittpunkte, aber keine Gewerkschaften), und jede Sprache mit struktureller Untertypisierung (ich denke, OCaml ist ein Beispiel) oder ein Typsystem, das leistungsfähig genug ist, um dies zu emulieren (Haskell ist ein klassisches), verfügt über vollständige "Typen als Mengen" "Fähigkeiten, zumindest innerhalb des Fragments seines Typsystems, das solche Dinge akzeptiert (relevant, wenn es ala HList / OOHaskell emuliert wird).

Da ich OCaml nicht sehr gut kenne, gebe ich den Teil Ihres Beispiels an, der in Scala funktioniert:

trait A {
  def a(): Unit
  def b(): Unit
}

abstract class B { // just to prove it works with both traits and classes
  def b(): Unit
  def c(): Unit
}

type C = A with B
type D = { def b(): Unit } // not an exact translation, because unions aren't directly available
// type `E` is unrepresentable

Eine Version für Haskell hängt von dem von Ihnen verwendeten Aufzeichnungssystem ab und ist wahrscheinlich etwas umständlich, da sie eher emuliert als nativ unterstützt wird.

Soweit ich weiß, sind in Ceylon sowohl Schnitt- als auch Vereinigungstypen mit voller Leistung in die Sprache integriert, sodass Sie vermutlich ein "xor" auf Textebene in Bezug auf diese codieren können.

Pthariens Flamme
quelle
1

Java unterstützt in einigen Kontexten Schnittpunkte von Schnittstellentypen, obwohl dies meines Erachtens die Erstellung von Variablen für Schnittpunkttypen nicht zulässt. Schnittpunkttypen können beispielsweise bei Verwendung des ? :Operators ins Spiel kommen . Wenn der zweite und der dritte Operand für diesen Operator nicht verwandte Schnittstellen sind, die von überlappenden Schnittstellensätzen erben, ist das Ergebnis des Operators der Satz von Schnittstellen, die beiden gemeinsam sind.

Superkatze
quelle
0

Mit Common Lisp können Sie neue Typen mit den Operatoren ,, und definieren (siehe Typspezifizierer not, die kombiniert werden ).andor

Core-Dump
quelle