Benannte Typen
TL;DR
- Ein benannter Typ ist ein registrierter pipelang-Typ —
Image,BoundingBox,AudioFrame,Tensorund weitere Einträge im type-catalog der Plattform —, den components aus ihreninput_type- undoutput_type-Deklarationen referenzieren. - Benannte Typen sind das gemeinsame Vokabular der Plattform für domänengeformte Daten. Dasselbe
Imagelöst sich für jedes bildverarbeitende component zur selben Definition auf; dasselbeBoundingBoxlöst sich für jeden Detektor zur selben Definition auf. Der benannte Typ liegt zwischen den Sprachprimitiven und dem contract jedes components. - Das Typsystem löst einen benannten Typ auf, wenn zwei Vertices verbunden werden: ein übereinstimmender Name und eine übereinstimmende strukturelle Form lassen die Kante zustande kommen; alles andere wird beim connect-Aufruf abgelehnt, bevor die Operation aufgezeichnet wird.
- Der catalog benannter Typen ist schreibgeschützt für workspace-Nutzer. Durchsuche ihn mit
ppl type list / get / print / tree; referenziere die Namen auscomponent.yml. Der catalog selbst wird von der Plattform kuratiert. - Benannte Typen lassen sich mit dem Rest der Typsprache kombinieren. Eine Liste von bounding boxes ist
[BoundingBox]; ein optionales Bild istMaybe<Image>; ein record, der beides trägt, ist{img: Image, boxes: [BoundingBox]}. Die strukturellen Konstruktoren leben in der Sprache; die benannten Typen leben im catalog; beide arbeiten in jeder Deklaration zusammen.
Warum benannte Typen als eigenständiges Konzept existieren
Ein benannter Typ ist ein einzelner catalog-Eintrag, der einer wiederkehrenden Domänenform einen kanonischen Namen gibt, sodass jedes component, das diesen Namen referenziert, zur selben Definition aufgelöst wird. Er existiert neben den atomaren Typen der Sprache (Int64, Double, String, Bool) und den zusammengesetzten Konstruktoren (lists, tuples, records, unions), die jede Form bereits strukturell ausdrücken können.
Strukturelle Ausdrückbarkeit und gemeinsame Identität sind verschiedene Dinge. Ein Bild ist strukturell ein record aus atomaren Typen plus einer Bytes-Nutzlast — seine Pixelabmessungen, sein Pixelformat und die kodierten Daten. Würde jedes bildverarbeitende component seine eigene Kopie dieses records deklarieren, trügen zwei strukturell identische records kein Signal, dass sie dieselbe Art von Wert beschreiben, und das Typsystem würde Namensabgleich als nicht verfügbar behandeln und allein auf strukturellen Vergleich zurückfallen. Ein benannter Typ liefert die gemeinsame Identität, die der strukturelle Vergleich nicht bieten kann.
Image ist der kanonische Name der Plattform für einen typisierten Bildwert: seine width und height, sein Pixel-format und die kodierten data, verpackt als ein benannter Typ, den jedes bildverarbeitende component referenziert. Wenn ein vertex input_type: Image deklariert, löst das Typsystem ihn zu dieser Definition auf, und jeder vertex, der output_type: Image deklariert, kann damit verdrahtet werden. Der gemeinsame Name ist es, der es den beiden Enden erlaubt, sich zu komponieren, ohne ihre Struktur erneut anzugeben.
Dasselbe gilt für AudioFrame (ein data-tensor plus einer sample_rate), Tensor<t> (eine shape plus den Element-data, parametrisiert durch den Elementtyp), BoundingBox (eine erkannte class plus ein rectangle), Landmark (ein point plus eine confidence) und den Rest des catalogs. Jeder ist ein contract zwischen component-Autoren: ein component, das einen bestimmten Namen ausgibt, erzeugt die Form dieses Namens mit der Bedeutung dieses Namens. Der catalog hält diese contracts.
Mentales Modell
component author backend author
┌──────────────────────────────┐ ┌────────────────────────┐
│ component.yml: │ │ ppl backend connect │
│ input_type: Image │◀─▶│ --from-vertex 1 … │
│ output_type: [BoundingBox] │ │ --to-vertex 2 … │
└──────────────────────────────┘ └────────────────────────┘
│ │
│ resolves via │
▼ ▼
┌───────────────────────────────────────────────────────────┐
│ named-types catalog (per remote) │
│ Image := { ... } │
│ BoundingBox := { ... } │
│ AudioFrame := { ... } │
└───────────────────────────────────────────────────────────┘
Der component-Autor schreibt einen Namen in das Manifest; der backend-Autor verdrahtet zwei Vertices; das Typsystem löst beide Enden gegen den catalog auf und validiert die Verbindung. Der catalog ist es, der den Namen über components hinweg Bedeutung verleiht — er löst jeden Namen zu einer einzigen Definition auf, statt es dem Typsystem zu überlassen, Strukturen allein zu vergleichen.
Siehe Typen, wie sich benannte Typen mit atomaren und zusammengesetzten Typen kombinieren, und Components, wo die Namen in component-Manifesten auftauchen.
Wie sich benannte Typen mit dem Rest der Typsprache kombinieren
Verwende diesen Rahmen immer dann, wenn du dich fragst „kann ich diesen benannten Typ in eine list / ein tuple / einen record verpacken".
Ja. Benannte Typen sind erstklassige Werte in der Typsprache; überall dort, wo ein Typ erscheinen kann, kann ein benannter Typ erscheinen — [BoundingBox] ist eine list von Erkennungen, genau wie [Int64] eine list von Ganzzahlen ist. Die Kompositionsregeln sind dieselben, ob der innere Typ atomar, zusammengesetzt oder benannt ist, und das Verpacken eines benannten Typs verliert keine seiner semantischen Garantien. Typen behandelt, wie sich die drei Kategorien kombinieren und wie der Typprüfer die zusammengesetzte Struktur durchläuft, wenn er eine Kante validiert.
Wie der catalog kuratiert wird
Verwende diesen Rahmen beim ersten Mal, wenn du dich fragst „kann ich meinen eigenen benannten Typ hinzufügen".
Der catalog benannter Typen ist aus der Sicht eines workspace-Nutzers schreibgeschützt. Die für workspace-Nutzer verfügbaren Verben sind list, get, print und tree — allesamt Abfragen. Es gibt keinen create-Pfad auf der Nutzeroberfläche; der catalog wird von der Plattform kuratiert, und Einträge werden über einen separaten Prozess hinzugefügt.
Diese Einschränkung folgt daraus, dass benannte Typen gemeinsame contracts sind. Image zum catalog hinzuzufügen verpflichtet jedes künftige bildverarbeitende component auf diese Form; es später zu ändern würde jedes component brechen, das die frühere Definition referenziert hat. Den catalog zentral zu kuratieren, statt Nutzer ihre eigenen Einträge definieren zu lassen, ist es, was jede Definition über die Components hinweg konsistent hält, die sie referenzieren.
Für eine Form, die noch keinen benannten Typ besitzt, verwende einen zusammengesetzten Typ (einen record, ein tuple, eine list aus atomaren Typen), bis sich die Form stabilisiert. Strukturelle Typen stehen inline im Manifest, erfordern keine catalog-Einträge, und das Typsystem behandelt sie genauso wie benannte Typen — sie tragen keinen gemeinsamen Namen über components hinweg. Wenn eine Form breit genug wiederkehrt, um einen Namen zu rechtfertigen, schlage ihre Aufnahme in den catalog über den Prozess vor, den die Plattform dafür bereitstellt.
Den catalog durchsuchen
Verwende dies, wenn du wissen musst, welche Namen existieren oder was einer von ihnen strukturell ist.
Die Abfrage-Verben decken die vier Formen von „erzähl mir über diesen catalog" ab:
ppl type list # everythingppl type list --query Frame # substring filterppl type get AudioFrame # canonical definitionppl type get AudioFrame --recursive # plus every transitive dependencyppl type print AudioFrame # pipelang source suitable for piping into a .type fileppl type tree AudioFrame # structural AST showing how the type is builtppl type tree AudioFrame --depth 2 # cap the expansion depth
Das richtige Verb hängt von der Frage ab. list dient der Entdeckung; get liefert die kanonische Definition; print dient dem Weiterleiten der Definition in eine Datei; tree dient dem Verständnis der strukturellen Komposition (besonders nützlich, wenn zwei Vertices nicht verbunden werden können und der Nutzer genau sehen muss, wo die Formen voneinander abweichen).
Der catalog ist pro remote: das Wechseln zwischen remotes (production, staging, on-premise) kann denselben Namen zu unterschiedlichen Definitionen auflösen. Das ist beabsichtigt; remotes haben unabhängige Typregister, weil sich die kuratierte Menge der Plattform im Lauf der Zeit und pro Umgebung weiterentwickelt.
Wenn der connect-Aufruf einen benannten Typ ablehnt
Verwende diesen Rahmen beim ersten Mal, wenn ppl backend connect eine Kante mit einem „type mismatch"-Fehler verweigert.
Die häufigsten Formen von connect-Fehlern bei benannten Typen:
- Unterschiedliche Namen — ein vertex gibt
AudioFrameaus, der andere erwartetTensor. Die Namen stimmen nicht überein, daher wird die Kante verweigert. Die Lösung ist meist eine Transformation zwischen ihnen (oder, falls keine Transformation existiert, ein Konverter-component). - Deklarationsabweichung — beide Vertices referenzieren
Image, aber die beiden component-Releases deklarieren es mit unterschiedlichen strukturellen Wrappern oder Argumenten. Die Lösung ist, die beiden Enden abzugleichen, in der Regel indem man eines der components auf ein Release anhebt, dessen Deklaration passt. - Verpackungs-Mismatch — eine Seite gibt
Imageaus, die andere erwartet[Image]. Derselbe benannte Typ, anderer struktureller Wrapper. Die Lösung ist ein Transformations-component, das die Kardinalität überbrückt. - Lokale Überschattung — eine
.type-Datei in der component-Konfiguration des Arbeitsverzeichnisses überschattet die remote-Definition mit einer anderen Form. Die Lösung ist, aus einem sauberen Verzeichnis aufzulösen oder die lokale.typean den catalog anzugleichen.
ppl type tree <name> an beiden Enden ist das richtige Diagnosewerkzeug, um zu verstehen, warum die Strukturen nicht übereinstimmen. Es expandiert den Typ bis zu seinen Blättern, sodass der Abweichungspunkt sichtbar wird.
Wo das hineinpasst
Benannte Typen sind das gemeinsame Vokabular der Plattform für domänengeformte Daten. Sie liegen zwischen den Sprachprimitiven (strukturell geteilt, aber ohne Domänenbedeutung) und den typisierten contracts der components (die Bedeutung tragen, aber gemeinsame Namen zum Komponieren brauchen). Der catalog hält die Definitionen; zentrale Kuratierung hält sie konsistent; den catalog für Nutzer schreibgeschützt zu halten verhindert, dass sich einmalige Definitionen vermehren. Weil die Namen echte Typen sind, erzwingt der Typprüfer sie strikt — Image verbindet sich mit Image, niemals mit einem strukturellen Doppelgänger, über jeden Draht im Graphen hinweg.
Das Ergebnis ist, dass die Frage, ob das Bild eines components dieselbe Art von Wert ist wie das eines anderen, vom Typprüfer aus dem gemeinsamen Namen aufgelöst wird, statt es dem Nutzer zu überlassen, dies zu bestätigen.
Verwandtes
- Typen — atomare, zusammengesetzte und benannte Typen zusammen.
- Components — wo
input_type/output_typebenannte Typen referenzieren. - Backend-Operationen —
connectist das Verb, das benannte Typen zwischen zwei Vertices auflöst. - Typsyntax-Referenz — die vollständige pipelang-Grammatik, mit der sich benannte Typen kombinieren.
- Solutions — wie das gemeinsame Vokabular produktübergreifende Komposition unterstützt.