2015-07-06 6 views
10

Ich habe seit einigen Jahren in F # programmiert und es gibt ein "Problem", das mich seit einiger Zeit beschäftigt und ich nicht lösen konnte. Es ist kein Fehler, ich denke, es ist eine Designentscheidung, aber das Problem ist trotzdem: Gibt es eine Möglichkeit, die Implementierung von Interfaces zu verzögern (vielleicht ist das nicht das richtige Wort dafür), das heißt, sie nicht zu implementieren in der anfänglichen Definition, aber später, vielleicht in der gleichen Datei, nachdem ich ein Modul für den Typ implementiert habe. Ich werde mit einem vereinfachten Beispiel erklären: Angenommen, ich habe folgende Datenstruktur:Verzögerung der Implementierung von Schnittstellenmethoden?

type 'T MyCollection = 
     (*type definition*) 
     interface IEnumerable<'T> with 
      member this.GetEnumerator() = 
       (* I don't want to implement it here 
        because I still don't have the module 
        with a toSeq function *) 

Wenn ich die Methode genau dort umgesetzt wird, würde ich auch alle Funktionen als Methoden des Typs implementieren und dann der Modul wäre nur ein "Proxy" für den Aufruf der Methoden. Auf diese Weise erstelle ich eine OO-first-Datenstruktur und erstelle dann ein Modul (mit Typ-Annotationen überladen), um eine funktional erstmalige Verwendung zu ermöglichen. Ich würde lieber eine funktional erste Datenstruktur schreiben (sauberer, da die Typinferenz besser funktionieren kann) und dann einen OO-Wrapper erstellen, um eine bessere Intellisense-Unterstützung für Sprachen wie C# zu ermöglichen. Dieser Ansatz entspricht dem, was die Entwurfsrichtlinien für F # angeben, aber die Schnittstellen können nicht überall implementiert werden, sondern in der ursprünglichen Definition des Typs. Diese Einschränkung zwingt mich, die gesamte Datenstruktur mit Mitgliedern zu schreiben. Ich habe nach Beispielen gesucht und ich habe festgestellt, dass die Liste Implementierung in FSharp.Core list genau das tut, was ich will, aber ich kann das nicht tun, der Compiler wird mich nicht lassen. Ich bin mir fast sicher, dass dies eine Designentscheidung ist, vielleicht, um schlechte Praktiken zu vermeiden, weiß ich nicht, aber ich halte meinen Wunsch, eine schlechte Praxis zu sein, nicht für notwendig. Ich bin mir auch der linearen Natur des fsharp Compilers bewusst.

Bitte, wenn jemand von Ihnen weiß, was ich tun soll, werde ich mich freuen, wenn Sie mir sagen. Auch wenn einer von euch weiß, warum ich diesem Ansatz nicht folgen sollte, werde ich das auch gerne wissen. Es muss einen Grund geben, warum dies für niemanden ein Problem ist.

Vielen Dank im Voraus.

Antwort

9

Ich stimme völlig zu, dass dies ein unglückliches Problem ist. Der Trick, der im Quellcode von 'a list in der F # -Kernbibliothek verwendet wird, besteht darin, die Implementierung der Schnittstelle in einer Typ Augmentation zu definieren. Der Compiler beschwert sich nicht, wenn Sie auf diese Weise einem Typ Member hinzufügen, aber es besagt, dass das Hinzufügen einer Implementierung einer Schnittstelle auf diese Weise veraltet ist. Das hindert Sie jedoch nicht daran. Die folgenden kompiliert für mich in Ordnung:

open System.Collections 
open System.Collections.Generic 

type MyCollection<'T> = 
    { Data : 'T list } 
    interface IEnumerable<'T> 
    interface IEnumerable 

let getEnumerator { Data = d } = 
    (d :> seq<_>).GetEnumerator() 

type MyCollection<'T> with 
    interface IEnumerable<'T> with 
    member this.GetEnumerator() = getEnumerator this 
    interface IEnumerable with 
    member this.GetEnumerator() = (getEnumerator this) :> _ 

Die Tatsache, dass dies veraltet ist, ist ein bisschen bedauerlich. Ich mag diesen Stil und ich benutze ihn, wenn es Sinn macht. Sie können start a discussion about this on F# user voice und vielleicht könnte es zurück in ein normales akzeptiertes Merkmal verwandelt werden :-)

+0

Danke für die Antwort, ich war wirklich beschämt, dass ich Dinge in meinem Verständnis falsch bekommen könnte. Bis jetzt habe ich dieses Problem auf meine eigene Art und Weise behandelt, da alle meine F # -Codes für den privaten Gebrauch bestimmt waren. Ich musste keine gute Schnittstelle für OO-Sprachen bereitstellen. Aber vor kurzem habe ich fsharpx.collections eine Implementierung eines SkewBinomialHeaps hinzugefügt (immer noch in einer Pull-Anforderung) und musste dies in einer konventionelleren und öffentlich akzeptierbaren Weise behandeln. –

+0

Ja, diese Lösung funktioniert einwandfrei. Aber ich fürchte, in einer zukünftigen Version der Sprache könnte sich das von veraltet zu illegal ändern. Danke noch einmal. –

+0

[Benutzerstimme eingereicht] (http://fslang.uservoice.com/forums/245727-f-language/suggestions/8733178-revert-back-to-an-accepted-feature-the-delayed -imp) –

Verwandte Themen