Zwei Arten der Kopplung

Kopplung über die Form und Kopplung über die Fallliste. Woher sie kommen, was sie kosten, was sie mildert. Lernseite, keine Empfehlung.

Stand 09.11.2026. Jede Aussage trägt ihre Marke. Ein Tipp zeigt die Quelle.

In drei Sätzen

  1. Die beiden Konzepte sind keine Gegensätze. Ein strukturelles Interface koppelt über die Form, ein Summentyp über die Liste der Fälle. Jede Sprache mit beidem zeigt, dass sie nebeneinander gehen.
  2. Der Grundkonflikt offen gegen geschlossen ist seit bekannt. Bis heute gibt es keine billige Lösung. Was sich leicht mildern lässt, ist fast nur Sichtbarkeit: Go kann seine Kanten sichtbarer machen, Rust seine Wildcards verbieten.
  3. Empirisch ist die Lage dünn. Direkt gemessen ist nur der mögliche Nutzen struktureller Typen in Java. Einen Vergleich von Summentypen mit Interfaces fand die Recherche nicht.

Was die Marken sagen

Mit unseren Proben ist eine Haushalts-App gemeint, einmal in Go und einmal in Rust gebaut. Die Grenzen der Proben stehen unter Unsere Proben.

Die zwei Arten

Ein Interface koppelt über die Form. Ein Summentyp koppelt über die Fälle.

Kopplung über die Form

Anbieterkennt keinenVerbraucher Verbraucherbraucht nurdiese Form keine Kante im Build

Der Anbieter kennt den Verbraucher nicht. Wer ihn nutzt, sieht man nur zur Laufzeit oder per Suche.

Kopplung über die Fallliste

Fall A, Fall B, Fall C die ganze Liste neuer Fall Stellegemeldet Stellegemeldet Stellegemeldet

Jeder Verbraucher hängt an der ganzen Liste. Kommt ein Fall dazu, meldet der Compiler jede Stelle.

Die Karte

Die beiden Konzepte stehen nicht auf einer Achse. Alle vier Felder sind besetzt. Ein Tipp auf eine Sprache zeigt mehr.

Fälle offenjeder darf ergänzen
Fälle geschlossenCompiler kennt alle
Passt über die Form
Passt über den Namen

Go-Interface

Ein Interface ist eine Menge von Methoden, ohne implements.

Niemand erklärt die Passung. Sie gilt von selbst. Keine Kante, keine Spur im Build.

Die dritte Achse: Wer erklärt die Passung, und wo steht das?

Unsere Beobachtung war: Go koppelt leicht und unsichtbar, Rust mit Aufwand und sichtbar. Das liegt auf keiner der beiden Achsen. Es liegt auf einer dritten.

Niemand, sie gilt von selbst

Go TypeScript Python Protocol

Keine Kante. Keine Spur im Build.

Nur Typ oder Vertrag dürfen sie erklären

Rust, Orphan-Regel

Kante sichtbar. Sonst ein Adapter.

Nur der Typ selbst

Java, C#

Der Typ muss den Vertrag kennen.

Jeder darf, mit Warnung

Haskell, Orphan-Instanzen Swift, @retroactive

Spur vorhanden, aber zwei Antworten möglich.

Zwei Linien

Links die Summentypen, rechts die strukturelle Passung. Die Reihe folgt der Zeit, die Abstände nicht. CLU steht in beiden.

  1. McCarthy Abstrakte Syntax mit Fällen. Vermutete Quelle für Landin.
  2. Landin, ISWIM Daten „ist entweder … oder …“. Nur eine Konvention, nicht geprüft.
  3. Algol 68 union mit Etikett, Auswahl über case.
  4. Pascal Varianten-Records. Das Etikett pflegt der Programmierer selbst.
  1. Smalltalk Duck Typing, dynamisch. Wer die Nachricht versteht, passt.

CLU steht in beiden Linien

oneof und variant als eingebaute Tagged Unions.
where t has …. Der Compiler prüft die Operationen eines Typ-Parameters nach Name und Signatur.

Getrennte Mittel für getrennte Aufgaben.

  1. Burstall, NPL Typen mit Konstruktoren und Pattern Matching.
  2. Hope Der Typ und alle Konstruktoren stehen an einem Ort. Geburt des geschlossenen datatype.
  3. Standard ML Übernimmt Datatypes und Pattern Matching aus Hope.
  4. Maranget Algorithmus für nicht erschöpfende und nutzlose Fälle, in OCaml eingebaut.
  5. Rust Algebraische Datentypen und Pattern Matching aus SML und OCaml.
  6. TypeScript Tagged Unions über eine gemeinsame Eigenschaft.
  7. Java 17 sealed als Grundlage für erschöpfende Muster.
  8. C# 15 union und closed. .NET 11 ist noch Vorabversion.
  1. Cardelli Strukturelle Subtypen, formal.
  2. Modula-3 Strukturelle Gleichheit als Regel, BRANDED als Ausnahme.
  3. Garrigue, OCaml „Structural polymorphism“ für Varianten.
  4. Go Interface ist eine Menge von Methoden, ohne implements.
  5. TypeScript Strukturell, weil JavaScript so geschrieben wird.
  6. Python, PEP 544 „Static duck typing“ neben dem nominalen Weg.

Hope: geschlossen wegen schnellem Code

Vor Hope war der Fall offen. NPL erlaubte, Konstruktoren einzeln zu deklarieren. Hope schloss die Liste nicht aus Gründen der Sicherheit, sondern für schnellen Code beim Pattern Matching.

Die Vollständigkeitsprüfung kam als Nutzen hinzu.

Modula-3: BRANDED trennt gleiche Formen

Die Sprache prüfte strukturell. Sie gab ein Wort, um zwei gleich geformte Typen zu trennen.

„Brands distinguish types that would otherwise be the same“

Marken unterscheiden Typen, die sonst gleich wären. TypeScript-Nutzer fordern dasselbe in Issue 202, mit , offen.

Rust begann strukturell. Frühe Fassungen hatten strukturelle Records. Sie wurden entfernt.

Was passiert, wenn …

Nur Fälle, die die Recherche belegt. Fehlt ein Beleg, steht das dort. Ein Tipp auf einen Fall zeigt beide Seiten.

Ein neuer Fall kommt dazu

Bei Kopplung über die Form

Reynolds, laut Cook: Objekte erleichtern neue Darstellungen.

Bei der Probe „Neuer Zustand“ gab es in Go kein Werkzeug, das die Stelle meldet.

exhaustive fängt fehlende Fälle. Es braucht aber einen switch an der Stelle.

Bei Kopplung über die Fallliste

Der neue Fall bricht jeden Verbraucher. Für Cargo ist das ein „Major“-Bruch ohne #[non_exhaustive].

Der Compiler kennt alle Fälle. Das treibt den Umbau: Bei der Probe „Neuer Zustand“ meldete er die Stelle.

Was sie kosten

Vor- und Nachteile, einzeln mit Marke.

Strukturelle Interfaces

Was dafür spricht

  • Interfaces können definiert werden, ohne bestehenden Code zu ändern.
  • Keine Typ-Hierarchie, also auch keine Abhängigkeits-Hierarchie.
  • Der Verbraucher beschreibt nur, was er braucht. der Methodenparameter in Java ließen sich strukturell typisieren. Davon waren zu spezifisch deklariert. Bei gab es keinen passenden nominalen Typ. Die gefundenen Typen hatten im Mittel , die deklarierten .

Was dagegen spricht

  • Keine Kante im Build: , .
  • Die Form sagt nichts über die Bedeutung. Cook: „Pure object interfaces allow any structurally compatible implementation, thus the type system does not prohibit bad implementations.“
  • Zufällige Treffer: Mehr dazu beim Fall Gleiche Signatur oben.
  • Eine neue Methode bricht alle Implementierungen. In Go und in Rust .

Summentypen

Was dafür spricht

  • Der Compiler kennt alle Fälle. Bei der Probe „Neuer Zustand“ meldete er die Stelle, in Go gab es kein Werkzeug dafür.
  • Unmögliche Zustände lassen sich gar nicht erst bauen.
  • Der Fall trägt seine Daten mit, statt sie an einen String zu hängen.

Was dagegen spricht

  • Ein neuer Fall bricht jeden Verbraucher.
  • Geschlossen heißt: Fremde können nicht ergänzen. Eine feste Menge ist gut, solange man sie kennt. Für Erweiterung durch andere ist sie falsch.
  • Der Wildcard hebt alles wieder auf: Mehr dazu beim Fall _ im Match oben.
  • Die Prüfer haben selbst Fehler. Neuere Tests fanden Fehler in scalac, javac und ghc, vor allem bei rekursiven Typen.

Beides in einer Sprache

Viele Sprachen haben offene und geschlossene Mittel. Was geschieht, wenn beides sich trifft?

CLU (1977)

where-Klausel, oneof

Getrennte Mittel für getrennte Aufgaben.

OCaml

Objekte, polymorphe Varianten, datatype

Vollständig getrennt. Polymorphe Varianten sind sicher, aber „a weaker type discipline“.

TypeScript

Interface, Union

Beide strukturell. Erschöpfung nur über never als Idiom.

Scala 3

Traits, enum, Selectable

Strukturell nur per Reflexion, „much slower“.

Java 17, Kotlin

sealed interface

Ein Interface, dessen Implementierungen feststehen. Hier fallen beide Konzepte in einem Konstrukt zusammen.

Rust

trait, enum, „sealed trait“-Muster

Das Buch nennt die Regel: enum für eine feste Menge, Trait-Objekt für eine offene. Sealed Trait: Cargo nennt es als Technik.

C# 15

union, closed, Interface

closed gilt für Klassen. Geschlossene Interfaces sind noch nicht drin.

Wo beides da ist, entsteht kein Durcheinander. Die Sprachen trennen die Aufgaben. Der eine echte Konflikt ist bei Go der Nullwert.

Go hat beides nicht direkt

Die FAQ sagt: Varianten „overlap in confusing ways with interfaces“. Sie überlappen auf verwirrende Weise mit Interfaces.

  1. Issue 19412, Summentypen. läuft
  2. Issue 57644: Unions in Interfaces erlauben. Der Vorschlag sagt selbst: in naher Zukunft nicht zu erwarten.
  3. neild, 76920: Unions in Interfaces sind der falsche Weg. Der Nullwert von Interfaces wäre nil, und der Vorschlag zwinge zwei verschiedene Konzepte zusammen. Auch dieser Vorschlag sagt selbst: in naher Zukunft nicht zu erwarten.
  4. Vorschlag 80607 vom Go-Team abgelehnt. Ian Lance Taylor nannte den Nutzen zu klein für die Kosten. abgelehnt
  5. offen
    PR 80467 von RestartFU baut enum in einem eigenen Fork. Angenommen ist er nicht. offen

Mit Summentypen in Go ist in absehbarer Zeit nicht zu rechnen.

Was die Nachteile mildert

Jedes Mittel mit seinen Kosten. Filter nach Art oder Nachteil engen die Liste ein.

Art

Nachteil

var _ I = (*T)(nil)

Sprache, Go

Wirkt auf: unsichtbare Passung

Kosten: eine Zeile je Paar

Marker-Methode ImplementsFooer

Bauweise, Go

Wirkt auf: zufällige Treffer

Kosten: „limit the utility of the interface idea“

Unexportierte Methode

Bauweise, Go

Wirkt auf: fremde Implementierungen, geschlossene Menge

Kosten: Interface nicht mehr offen

gopls: Implementierungen suchen

Werkzeug, Go

Wirkt auf: unsichtbare Passung

Kosten: nur auf Anfrage, außerhalb des Pakets nur exportierte

exhaustive

Werkzeug, Go

Wirkt auf: fehlende Fälle, auch bei Type Switches

Kosten: braucht einen switch an der Stelle

go-check-sumtype

Werkzeug, Go

Wirkt auf: fehlende Fälle bei Interface mit Marker

Kosten: //sumtype:decl, ein default zählt als erledigt

Marke (BRANDED, Brand-Idiom)

Sprache oder Bauweise

Wirkt auf: zufällige Treffer

Kosten: mehr Text je Typ

#[non_exhaustive]

Sprache, Rust

Wirkt auf: Bruch durch neuen Fall

Kosten: zwingt zum Wildcard, verliert Erschöpfung außerhalb der Crate

@unknown default

Sprache, Swift

Wirkt auf: beides zugleich

Kosten: Warnung bei bekannten Fällen, trotzdem kompatibel

Wildcard-Verbot

Werkzeug

Wirkt auf: stumme Wildcards

Kosten: etwas mehr Text.

Bei uns schon an.

Sealed Trait

Bauweise, Rust

Wirkt auf: fremde Implementierungen

Kosten: Muster, kein Sprachmittel

Eigenes Vertrags-Crate oder Adapter

Bauweise, Rust

Wirkt auf: Orphan-Regel

Kosten: zusätzliche Fläche

Die Orphan-Regel ist selbst ein Gegenmittel

Die Orphan-Regel verhindert, dass zwei Crates (Rust-Pakete) dieselbe Passung verschieden erklären. Matsakis nennt die Alternative: Man müsste festlegen, welche Implementierung gerade gilt.

Haskell lässt Orphans zu, mit Warnung -Worphans. Swift warnt seit 6.0, und @retroactive schaltet die Warnung ab. Rust hat die Regel mit RFC 2451 gelockert.

Gegen das Expression Problem selbst

Wadler, : „add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety“. Also neue Fälle und neue Funktionen, ohne Neukompilieren, typsicher.

Zeilen sind Fälle, Spalten Funktionen. Funktionale Sprachen legen die Zeilen fest. Objektorientierte Sprachen legen die Spalten fest.

Reynolds sah das schon , laut Cook. Das Expression Problem liegt auf der Achse offen/geschlossen. Mit der Form-Achse hat es nichts zu tun.

Visitor plus Erweiterung

OO-Muster mit Fällen und Operationen.

Kosten: viel Zeremonie, jede Klasse braucht accept.

Polymorphe Varianten

Die Fälle sind strukturell.

Kosten: schwächere Typdisziplin, Annotationen nötig. Beleg:

Data types à la carte

Typen aus Bausteinen, in Haskell.

Kosten: Typklassen mit Überlappung und Erweiterungen.

Object Algebras

Fabrik-Interface, einfache Generics, kein accept.

Kosten: etwas neue Denkweise, in Java machbar. Beleg:

Tagless Final

Die Sprache als Typklasse, keine Etiketten.

Kosten: abstrakt. Beleg:

Keine davon bringt beides umsonst. Für eine Anwendung mit einer Handvoll Zustände und wenigen Modulen ist jede dieser Lösungen überdimensioniert. Das ist Bibliotheks-Technik.

Was belegt ist

Von gemessen bis nur Meinung. Oben ist der Boden fest, unten fehlt er.

  1. Gemessen, auf genau dieser Achse

    Nützt strukturelle Typisierung in nominalem Code? Gemessen an Potenzial, kein Vergleich mit Menschen. .

    Wie oft trifft eine Passung zufällig? Gemessen an : .

  2. Gemessen, aber auf einer anderen Achse

    Typen finden Fehler: öffentlicher JavaScript-Bugs.

    Sprache und Fehlerquote: Sehr kleine Effekte, nur signifikant.

    Statische Typen allgemein: Helfen bei undokumentiertem Code und Typfehlern, nicht bei Logikfehlern.

  3. Beobachtet, ohne Zahl

    Hilft Vollständigkeitsprüfung gegen Fehler? Beobachtung, keine Zahl. Lubin und Chasins, qualitativ.

    KI-Agenten beim Programmieren, mit Summentypen oder Interfaces: Nur unsere Proben. .

  4. Nur Begründung, keine Messung

    Orphan-Regel, Go-FAQ, Pike: Begründung der Designer, keine Messung.

  5. Nicht gefunden

    Ist das in Go auch so? Nicht gefunden.

    Summentyp gegen Interface im direkten Vergleich? Nicht gefunden.

offen Was fehlt

  • Keine direkte Vergleichsstudie von Summentypen und Interfaces.
  • Keine Studie zu Go-Interfaces im Großen.
  • Keine Studie zu KI-Agenten und einem der beiden.

Die Malayeri-Studie ist die einzige, die genau diese Achse misst. Sie selbst sagt: „one must study the way structural subtyping is eventually used by mainstream programmers“. Man müsse also noch untersuchen, wie Programmierer strukturelle Typen tatsächlich nutzen.

Was das für unsere Proben heißt

Orientierung, keine Empfehlung. Kosten grob.

Was die Proben sind und was nicht

Unsere Proben stammen aus einer Haushalts-App. Wir haben sie einmal in Go und einmal in Rust gebaut.

Zwei Einschränkungen gelten für jeden Befund. Erstens: . Jede Probe lief je Fassung nur einmal. Zweitens: Es sind zugleich zwei Bauweisen. Ein Unterschied kann also an der Sprache liegen oder an der Bauweise.

In Go

var _ orders.Customers = (*customers.Module)(nil) (Beispiel) an der Stelle, die die Module zusammensteckt

Die drei Verträge

Die Passung steht im Code. Bricht früher.

Klein. Keine Kante im Build.

Richtungsliste als Test

Architektur-Test

Macht die Probe „Beide Module brauchen einander“ sichtbar.

Klein. Liste von Hand. Schon vorgeschlagen

exhaustive einschalten

Linter-Konfiguration, heute nicht aktiv

Fängt fehlende Fälle, wo ein switch steht.

Klein. Findet nichts ohne switch.

Eine Funktion mit switch je Zustandstyp

Die Zustandstypen der App

Schafft die Stelle, die exhaustive braucht. Die Probe „Neuer Zustand“ hätte einen Treffer.

Klein. Disziplin, kein Zwang.

Interface mit Marker und go-check-sumtype oder exhaustive -check=typeswitch

Zustände mit Daten je Fall

Nähe zum Summentyp.

Mittel. Ein Typ je Fall, Umbau an DB und Draht. default hebt es auf.

Keine dieser Stellen ersetzt den Compiler. Sie hängen alle daran, dass jemand den switch schreibt.

In Rust

Wildcard-Verbot

Schon aktiv

Fängt stumme Wildcards. Deckt genau den Befund aus ab.

Keine.

Vertrags-Crate

Anbieter-Crate und Verbraucher

Kanten weg, ein Trait statt drei.

Neue Crate, ADR

Adapter in der App-Crate

—

wie in Go.

Die App-Crate übersetzt dann fachlich

#[non_exhaustive]

nirgends sinnvoll

—

Erzwingt außerhalb der Crate einen Wildcard. Bei uns sind Crate-Grenzen Modulgrenzen. Der Compiler-Bruch ist dort gerade der Nutzen.

Was die Literatur zu unseren Proben sagt

  • Die Proben „Neuer Zustand“, „Ein Pflichtfeld“, „Zustände im Typ“ (Rust besser, Sprache) passen zur Linie. Der Gewinn ist seit Hope bekannt, und das ist der geschlossene Fall.
  • Die Proben „Aufruf zwischen Modulen“, „Beide Module brauchen einander“ (Go billiger, Rust sichtbarer) passen zur dritten Achse. Sie gehören nicht zum Expression Problem.
  • Nirgends bei uns wird das Expression Problem zum Hindernis. Module erweitert nur unser eigener Code.
  • Die Literatur stößt unsere Proben nicht um. Sie stützt die zwei Seiten, die wir schon gemessen haben.

Typische Irrtümer

„Interfaces und Summentypen schließen sich aus.“

Falsch. Java 17 hat sealed interface. TypeScript hat beides. Rust hat beides. Der Satz der Go-FAQ gilt für Go, nicht allgemein.

„Strukturell heißt unsicher.“

Falsch. Go prüft die Passung beim Kompilieren. TypeScript ist an anderen Stellen unsound, nicht wegen der Struktur.

„Nominal heißt: Kante sichtbar.“

Nur teilweise. Bei Rust kommt die Kante von Cargo und der Orphan-Regel. In Haskell sind Orphans unsichtbar erlaubt.

„Ein Trait ist ein Java-Interface.“

Nein. Ein Trait darf auch beim Vertrag stehen, nicht nur beim Typ. Das Erbe sind Typklassen.

„Summentypen sind etwas Modernes.“

Nein. Hope hatte das Konzept fertig.

„Der Compiler findet die Fehler.“

Er findet die Stelle. Was dort richtig ist, entscheidet jemand anderer. Ein _ schaltet ihn ab.

„Go bekommt das bald.“

Issue 19412 läuft . Neuer Vorschlag abgelehnt. Offener Punkt: der Nullwert.

„0 Kanten heißt: entkoppelt.“

Nein. Zur Laufzeit hängen die Module weiter aneinander, wie die Probe „Beide Module brauchen einander“ zeigt.

„Expression Problem muss man lösen.“

Nein. Fast alle Anwendungen wählen eine Seite, und das ist vertretbar. Lösungen brauchen Bibliotheks-Technik.

Nicht belegt

Quellen

Die Nummern dienen nur dem Nachschlagen.

  1. 1Wadler: The Expression Problem, 12.11.1998
    https://homepages.inf.ed.ac.uk/wadler/papers/expression/expression.txt
  2. 2Cook: On Understanding Data Abstraction, Revisited, OOPSLA 2009
    https://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf
  3. 3Reynolds: User-defined types and procedural data structures as complementary approaches to data abstraction, 1975. Nur über [2].
    Nur über Quelle 2, kein eigener Abruf.
  4. 4MacQueen, Harper, Reppy: The History of Standard ML, HOPL 2020
    https://doi.org/10.1145/3386336
  5. 5Wikipedia: Tagged union
    https://en.wikipedia.org/wiki/Tagged_union
  6. 6Liskov: A History of CLU, 1992
    https://www.cs.tufts.edu/~nr/cs257/archive/barbara-liskov/clu-history.pdf
  7. 7Cardelli, Donahue, Glassman, Jordan, Kalsow, Nelson: Modula-3 Report (revised), SRC RR 52, 1989
    https://softwarepreservation.computerhistory.org/modula3/doc/SRC-RR-52.pdf
  8. 8Cardelli: Publikationsliste, darin A Semantics of Multiple Inheritance (1984/1988), Structural Subtyping and the Notion of Power Type (POPL 1988)
    http://lucacardelli.name/indexPapers.html
  9. 9Garrigue: Programming with Polymorphic Variants, ML Workshop 1998
    https://caml.inria.fr/pub/papers/garrigue-polymorphic_variants-ml98.pdf
  10. 10OCaml Manual: Polymorphic variants
    https://ocaml.org/manual/polyvariant.html
  11. 11OCaml Manual: Objects
    https://ocaml.org/manual/objectexamples.html
  12. 12Pike: Go at Google, SPLASH 2012
    https://go.dev/talks/2012/splash.article
  13. 13Go FAQ
    https://go.dev/doc/faq
  14. 14Go Issue 19412: add sum types / discriminated unions, seit 05.03.2017, offen
    https://github.com/golang/go/issues/19412
  15. 15Go Issue 57644: sum types based on general interfaces, 05.01.2023
    https://github.com/golang/go/issues/57644
  16. 16neild: Go Issue 76920, sum types as a non-interface union type, 18.12.2025
    https://github.com/golang/go/issues/76920
  17. 17Go Issue 80607: define sum types as an extension of interfaces. Taylor 12.08.2026: „likely decline“, letzter Kommentar 09.09.2026, geschlossen
    https://github.com/golang/go/issues/80607
  18. 18Go PR 80467: all: add algebraic enum types, 19.07.2026, offen
    https://github.com/golang/go/issues/80467
  19. 19Go Blog: Keeping Your Modules Compatible, 2020
    https://go.dev/blog/module-compatibility
  20. 20gopls: Navigation
    https://go.dev/gopls/features/navigation
  21. 21nishanths/exhaustive
    https://github.com/nishanths/exhaustive
  22. 22alecthomas/go-check-sumtype
    https://github.com/alecthomas/go-check-sumtype
  23. 23Rust Reference: Influences
    https://doc.rust-lang.org/reference/influences.html
  24. 24Rust Reference: Implementations, Coherence
    https://doc.rust-lang.org/reference/items/implementations.html
  25. 25Matsakis: Little Orphan Impls, 14.01.2015
    https://smallcultfollowing.com/babysteps/blog/2015/01/14/little-orphan-impls/
  26. 26Rust RFC 2451: Re-Rebalancing Coherence
    https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html
  27. 27Rust RFC 2008: non_exhaustive
    https://rust-lang.github.io/rfcs/2008-non-exhaustive.html
  28. 28Cargo Book: SemVer Compatibility
    https://doc.rust-lang.org/cargo/reference/semver.html
  29. 29Rust Book: Using Trait Objects
    https://doc.rust-lang.org/book/ch18-02-trait-objects.html
  30. 30TypeScript Handbook: Type Compatibility
    https://www.typescriptlang.org/docs/handbook/type-compatibility.html
  31. 31TypeScript Handbook: Narrowing
    https://www.typescriptlang.org/docs/handbook/2/narrowing.html
  32. 32TypeScript 2.0 Release Notes
    https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html
  33. 33TypeScript Issue 202: non-structural (nominal) type matching, seit 22.07.2014, offen, 499 Kommentare beim Abruf
    https://github.com/microsoft/TypeScript/issues/202
  34. 34PEP 544: Protocols, 2017
    https://peps.python.org/pep-0544/
  35. 35JEP 409: Sealed Classes, Java 17
    https://openjdk.org/jeps/409
  36. 36Kotlin: Sealed classes and interfaces
    https://kotlinlang.org/docs/sealed-classes.html
  37. 37Swift SE-0192: Handling Future Enum Cases
    https://github.com/swiftlang/swift-evolution/blob/main/proposals/0192-non-exhaustive-enums.md
  38. 38Swift SE-0364: Warning for Retroactive Conformances
    https://github.com/apple/swift-evolution/blob/main/proposals/0364-retroactive-conformance-warning.md
  39. 39Microsoft: What's new in C# 15, Stand 19.10.2026
    https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-15
  40. 40Scala 3: Programmatic Structural Types
    https://docs.scala-lang.org/scala3/reference/changed-features/structural-types.html
  41. 41GHC User Guide: Orphan modules
    https://downloads.haskell.org/ghc/latest/docs/users_guide/separate_compilation.html
  42. 42Maranget: Warnings for pattern matching, JFP 2007
    http://moscova.inria.fr/~maranget/papers/warn/warn.pdf
  43. 43Binder, Ermantraut u. a.: The Algebra of Patterns, ECOOP 2025
    https://drops.dagstuhl.de/storage/00lipics/lipics-vol333-ecoop2025/LIPIcs.ECOOP.2025.2/LIPIcs.ECOOP.2025.2.pdf
  44. 44Lubin, Chasins: How Statically-Typed Functional Programmers Write Code, OOPSLA 2021, 30 Sitzungen, grounded theory
    https://doi.org/10.1145/3485532
  45. 45Malayeri, Aldrich: Is Structural Subtyping Useful? An Empirical Study, ESOP 2009
    https://www.cs.cmu.edu/~aldrich/papers/esop09.pdf
  46. 46Krishnamurthi, Felleisen, Friedman: Synthesizing Object-Oriented and Functional Design to Promote Re-Use, ECOOP 1998
    https://cs.brown.edu/~sk/Publications/Papers/Published/kff-synth-fp-oo/paper.pdf
  47. 47Swierstra: Data types à la carte, JFP 2008
    https://webspace.science.uu.nl/~swier004/publications/2008-jfp.pdf
  48. 48Oliveira, Cook: Extensibility for the Masses, ECOOP 2012
    https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf
  49. 49Carette, Kiselyov, Shan: Finally Tagless, Partially Evaluated, JFP 2009
    https://okmij.org/ftp/tagless-final/JFP.pdf
  50. 50Hanenberg u. a.: An empirical study on the impact of static typing on software maintainability, Empirical Software Engineering 19(5), 2014, S. 1335–1382. Nur Zusammenfassung aus dem Suchergebnis, ohne eigenen Abruf.
    Nur Zusammenfassung aus dem Suchergebnis, ohne eigenen Abruf.
  51. 51Gao, Bird, Barr: To Type or Not to Type, ICSE 2017
    https://janvitek.org/events/NEU/7575/pubs/no-type.pdf
  52. 52Berger u. a.: On the Impact of Programming Languages on Code Quality, TOPLAS 2019
    https://arxiv.org/abs/1901.10220
  53. 53Eigene Proben an einer Haushalts-App in Go und Rust (nicht öffentlich)
    Nicht öffentlich, ohne Link. n=1 je Probe, zwei Bauweisen.
  54. 54Validating Soundness and Completeness in Pattern-Match Coverage Analyzers, 2025. Nur Suchergebnis
    https://dl.acm.org/doi/10.1145/3763171
  55. FRust Internals: Why were structural records removed? Forumsbeitrag, einzige Quelle für diesen Punkt
    https://internals.rust-lang.org/t/why-were-structural-records-removed/1553
  56. AAllgemeinwissen, in der Recherche als solches markiert (Abschnitt Nicht belegt)
    Keine eigene Quelle.