JDL – Qualifier, Effektsystem, Konversionen und Wire-Integration¶
Status: Draft
Geltungsbereich: Sprachebene (keine VM-Implementierungsdetails)
Warum Dieses Dokument Existiert¶
Die Kernteile 00–03 beschreiben bereits die Architektur. In der Praxis bleiben aber vier Fragen offen, die beim Implementieren sofort relevant werden:
- Wie unterscheiden sich
phantom,reifiedundnarrowingpräzise? - Wo endet Protokollverhalten und wo beginnt Capability/Effekt?
- Wann sind Konversionen implizit zulässig, wann verboten?
- Wie wird Wire/Serde eingebunden, ohne Sonderlogik in die Sprache zu drücken?
Dieses Dokument schließt genau diese Lücke.
0. Priorität¶
Dieses Dokument konkretisiert:
00-refinements.md01-grundlagen.md02-typsystem.md03-runtime.md
Bei Widerspruch gelten immer 00 bis 03.
Bei Widerspruch mit 07-cast-effekte-refinements.md gilt 07.
1. Leseführung¶
- Abschnitt 2: Qualifier-Modi (rein semantische Schalter)
- Abschnitt 3–5: Verhalten, Effekte und Konversion als zusammenhängendes System
- Abschnitt 6: Wire/Serde als Anwendung derselben Bausteine
Leitidee: Keine Spezialmechanik, nur konsistente Komposition aus vorhandenen Sprachmitteln.
2. Qualifier-Modi¶
2.1 Grundsatz¶
Ein Qualifier-Modus verändert die Behandlung einer Bindung, nicht den Basistyp.
Er ist:
- signaturrelevant,
- typprüfungsrelevant,
- inferenzrelevant,
- codegen-relevant.
Er ist kein Refinement und kein Effekt.
2.2 phantom¶
Bedeutung:
- nur Compile-Zeit,
- keine Runtime-Repräsentation,
- keine Runtime-Reflection auf diesem Parameter.
2.3 reified¶
Bedeutung:
- Typinformation wird zur Laufzeit materialisiert,
- TypeInfo/Typecase auf Typparameter ist nur dann zulässig,
- Reifikation ist nie implizit.
2.4 narrowing¶
Bedeutung:
- keine implizite Anwendung,
- expliziter Cast-Aufruf erforderlich,
- Modus-Syntax ist erweiterbar (z. B. zukünftige Modi).
3. Protocol, Service, Provide¶
3.1 Warum Die Trennung Wichtig Ist¶
Viele Sprachsysteme vermischen Fähigkeiten eines Typs mit Capabilities der Außenwelt. JDL trennt das explizit:
protocol: Verhalten eines Typs,service: Capability in Effektkontexten.
3.2 protocol¶
Eigenschaften:
- kontextunabhängig,
- für Generics/
wheregeeignet.
3.3 service¶
Eigenschaften:
- effektrelevant,
- via Handler durch
providegebunden, - im Effect-Stil über
Effect[R, E, D]deklariert, - im imperativen Stil als Parameter übergeben.
3.4 provide-Formen¶
provide hat genau drei semantisch klar getrennte Formen:
provide Equatable for User { ... } // Protocol-Implementierung
provide User { ... } // Methoden am Typ
provide UserDb[PostgresHandler] { ... } // Service-Handler-Bindung
provide Target from Source existiert nicht mehr. Konversion läuft über
CastTo[T] (siehe 07-cast-effekte-refinements.md § 1).
Invarianten:
- Protocols erscheinen nicht im Effect-Typ
D. - Services werden nicht wie normale Protocol-Constraints behandelt.
4. Effektsystem¶
Überholt durch
07-cast-effekte-refinements.md§§ 2–3.Das
deps-Konstrukt auf Funktionsebene existiert nicht mehr.
Effect[R, E, D]ist ein normaler generischer Typ in der Stdlib — kein Compiler-Primitiv. Der Compiler hat kein Sonderwissen über diesen Typ. Die gesamte Semantik (Komposition, Retry, Remote, Concurrency) ist JDL-Code der auf diesem Typ aufbaut.JDL kennt zwei Stile um Abhängigkeiten zu Services auszudrücken:
Imperativer Stil — Service als normaler Parameter, sofortige Ausführung:
Effect-Stil —
Effect[R, E, D]als normaler Rückgabetyp, lazy:Der Funktionskörper beider Varianten ist identisch. Im Effect-Stil gibt die Funktion einen
Effect-Wert zurück der erst durch explizites Bereitstellen der Dependencies ausgeführt wird — das ist normale Typsemantik, kein Compiler-Sonderfall.Runtime-Verhalten wie Retry, Remote-Ausführung und Concurrency sind Refinements auf
CallGraph— ebenfalls ein normaler Stdlib-Typ:
5. Konversionssystem¶
Überholt durch
07-cast-effekte-refinements.md§ 1.Konversion läuft über
CastTo[T]. Die alte Formprovide Target from Sourceexistiert nicht mehr.
6. Wire-/Serde-Integration¶
6.1 Ziel¶
Wire-Serialisierung soll ohne externen Generator möglich sein, aber trotzdem typisiert und vorhersagbar.
6.2 WireType¶
protocol WireType[T] {
def kind() -> WireKind
def encodeValue(x: T, w: WireWriter) -> ()
def decodeValue(r: WireReader) -> Result[T, DecodeError]
}
6.3 Delegation Über Konversion¶
type UserId: struct { value: str }
provide CastTo[str]: Lossless for UserId { ... }
provide CastTo[UserId]: Try[ParseError] for str { ... }
Damit kann WireType[UserId] über WireType[str] delegieren.
6.4 Derive Für Message-Typen¶
Refinements auf einzelnen Feldern sind nicht zulässig — Feld-Metadaten wie Wire-Tags werden als Refinement auf dem Typ als Ganzes ausgedrückt:
Regeln:
- jedes Feld genau ein
tag(viaWireTags), - Tags eindeutig,
- Feldtyp selbst
WireTypeoder verlustfrei aufWireTypeabbildbar.
6.5 Effekttrennung¶
- reine Serialisierung bleibt ohne Service-Abhängigkeit,
- IO-gebundene Nutzung übergibt den Service als Parameter oder verwendet
Effect[R, E, IO].
7. Normative Invarianten¶
- Runtime-TypeInfo auf Typparameter nur mit
reified. phantombleibt runtime-inexistent.narrowingist nie implizit.Effect[R, E, D]ist ein normaler generischer Typ in der Stdlib — kein Compiler-Primitiv. Der Compiler hat kein Sonderwissen darüber. Abhängigkeiten werden überEffect[R, E, D]im Rückgabetyp oder als explizite Parameter ausgedrückt.depsals Funktionskonstrukt existiert nicht.- Im Effect-Stil gibt eine Funktion einen
Effect-Wert zurück — das ist normaler Rückgabetyp, kein Compiler-Sonderfall. Im imperativen Stil werden Services als Parameter übergeben. Fehlende Parameter sind normale Compile-Fehler des Typsystems. - Konversionen sind nicht transitiv.
- Protocol- und Service-Ebene bleiben getrennt.
- Wire-Delegation nutzt nur deklarierte Konversionen.
Addendum A – Formale Kurzsemantik¶
Das Addendum fasst die mathematischen Kernaussagen zusammen (Urteile, Effektordnung, Funktions-/Aufrufregeln, Reifikation, Konversion). Es ist als präzise Referenz gedacht, nicht als Einführungstext.