Ich habe die folgende diskriminierte Verbindung definiert:
%Vor%Dann habe ich eine hübsche Druckfunktion wie folgt erstellt:
%Vor% Nun möchte ich, dass mein Expr
-Typ diese Funktion für die Methode ToString()
verwendet. Zum Beispiel:
Aber ich kann das nicht, weil stringify
noch nicht definiert ist. Die Antwort ist, Stringify
als Mitglied von Expr
zu definieren, aber ich möchte meine ursprüngliche Typdeklaration nicht mit dieser spezialisierten Methode verschmutzen, die mit der Zeit weiter wachsen wird. Daher entschied ich mich, eine abstrakte Methode zu verwenden, die ich mit einer Erweiterung des intrinsischen Typs weiter unten implementieren konnte in der Datei. Folgendes habe ich getan:
Aber ich bekomme den folgenden Compilerfehler:
Fehler FS0912: Dieses Deklarationselement ist in einem nicht erlaubt Vergrößerung
Die Nachricht scheint nicht einmal richtig zu sein (ich erstelle noch keine Art Augmentation), aber ich verstehe, warum sie sich beschweren. Es will nicht, dass ich ein abstraktes Mitglied in einem diskriminierten Unionstyp erstelle, weil es nicht vererbt werden kann. Obwohl ich wirklich keine Vererbung möchte, möchte ich, dass sie sich wie eine partielle Klasse in C # verhält, wo ich sie woanders definieren kann (in diesem Fall die gleiche Datei).
Ich habe "betrogen", indem ich die spätbindenden Eigenschaften des Attributs StructuredFormatDisplay
zusammen mit sprintf
:
Obwohl nun sprintf
und ToString
beide den gleichen String ausgeben, gibt es keine Möglichkeit, den Add (Con 2,Con 3)
Output im Gegensatz zu (2 + 3)
zu erhalten, wenn ich es möchte.
Gibt es eine andere Möglichkeit zu tun, was ich versuche?
P.S. Ich habe auch festgestellt, dass es nicht funktioniert, wenn ich das Attribut StructuredFormatDisplay
anstelle des Originaltyps auf die Augmentation setze. Dieses Verhalten scheint mir nicht richtig zu sein. Es scheint, dass entweder der F # -Compiler das Attribut zur Typdefinition hinzufügen oder Attribute bei Typerweiterungen verbieten sollte.
Tatsächlich muss stringify
mit dem Datentyp wachsen , andernfalls würde es zu einer unvollständigen Musterübereinstimmung kommen. Jede wesentliche Änderung des Datentyps würde auch die Änderung von stringify
erfordern. Als persönliche Meinung würde ich darüber nachdenken, beide am selben Ort zu behalten, es sei denn, das Projekt ist wirklich komplex.
Da Sie jedoch bevorzugen, dass Ihr DU-Typ eindeutig ist, sollten Sie den Datentyp in einen DU-Fall einbetten:
%Vor%Zitat aus dieser Antwort :
In komplexen Programmen erleichtern eindeutige Typ-Signaturen die Aufrechterhaltung der Zusammensetzbarkeit.
Nicht nur das Hinzufügen von mehr Fällen zu Einzelfall-DUs ist einfacher, es ist auch einfacher, DUs mit Member- und statischen Methoden zu erweitern.
Haben Sie in Betracht gezogen, Ihre ToString
in der Augmentation zu definieren?
Allerdings hat die hässliche Nebenwirkung eines
%Vor%Wie wäre es mit einer Lösung, die nicht einmal eine Typendung benötigt?
Definieren Sie stattdessen einen Typ mit einem statischen Member, der stringify ist (wir benötigen den Dummy-Typ als type a ... and b
erfordert b
als Typ
Tags und Links f# discriminated-union type-extension