Ich versuche, Ente Eingabe in F # zu implementieren, und ich entdeckte, dass Sie eine Member-Einschränkung in haben können F # Generika wie folgt:
%Vor%Der obige Code wird jedoch nicht kompiliert, wenn ich versuche, die Eigenschaft zu referenzieren. Ich erhalte einen Compilerfehler:
Dieser Code ist nicht ausreichend generisch. Die Typvariable ^ T wenn ^ T : (member get_Name: ^ T - & gt; string) konnte nicht generalisiert werden, weil es würde seinem Umfang entgehen.
Ist es möglich, die Duck-Typisierung über eine generische Constraint zu implementieren?
In letzter Zeit gab es eine ähnliche Frage, wo Memberbeschränkungen in der Typdeklaration verwendet wurden .
Ich bin mir nicht sicher, wie ich das Beispiel korrigieren soll, um es kompilieren zu lassen, aber ich wäre nicht überrascht, wenn das nicht möglich wäre. Member-Constraints sind für die Verwendung mit statisch aufgelösten Typparametern und insbesondere mit inline
functions oder members gedacht und ich denke nicht, dass es idiomatischer F # -Code ist, sie mit Typparametern einer Klasse zu verwenden.
Ich denke, dass eine idiomatische Lösung für Ihr Beispiel wäre, eine Schnittstelle zu definieren:
%Vor% (Tatsächlich benötigt der ListEntryViewModel
wahrscheinlich keinen Typparameter und kann einfach INamed
als Konstruktorparameter verwenden, aber es kann ein Vorteil sein, ihn auf diese Weise zu schreiben.)
Nun können Sie immer noch die Enttippung verwenden und ListEntryViewModel
für Dinge verwenden, die Name
Eigenschaft haben, aber nicht die INamed
Schnittstelle implementieren! Dies kann durch Schreiben einer inline
-Funktion erfolgen, die INamed
zurückgibt und statische Membereinschränkungen verwendet, um die vorhandene Eigenschaft Name
einzufangen:
Sie können dann Ihr Ansichtsmodell erstellen, indem Sie ListEntryViewModel(namedModel someObj)
schreiben, wobei someObj
die Schnittstelle nicht implementieren muss, sondern nur die Eigenschaft Name
benötigt.
Ich würde diesen Stil bevorzugen, weil Sie mit einer Schnittstelle besser dokumentieren können, was Sie vom Modell erwarten. Wenn Sie andere Objekte haben, die nicht zum Schema passen, können Sie sie anpassen. Wenn Sie jedoch ein Modell schreiben, ist die Implementierung einer Schnittstelle eine gute Möglichkeit, um sicherzustellen, dass alle erforderlichen Funktionen verfügbar sind.
Ist es möglich, die Duck-Typisierung über eine generische Constraint zu implementieren?
Nein. Bis auf einige Spezialfälle implementiert F # nur eine nominale Eingabe, bei der die Eingabe von Enten nicht möglich ist. Wie die anderen Antworten erklärt haben, besteht die idiomatische "Lösung" darin, eine Schnittstelle zu allen Klassen nachzurüsten, die Sie an diese Schnittstelle gehalten haben, aber das ist natürlich in den meisten Fällen, in denen Sie Ente tippen möchten, unpraktisch.
>Beachten Sie, dass diese Einschränkung in F # von .NET geerbt wird. Wenn Sie eine praktischere Lösung sehen möchten, die mit der Eingabe von Enten vergleichbar ist, sollten Sie sich die strukturell typisierten polymorphen Varianten und Objekte von OCaml ansehen.