2010-12-19 7 views
16

Weiß jemand, warum dies nicht kompilieren?F # Schnittstelle Vererbung fehlgeschlagen aufgrund Einheit

type MyInterface<'input, 'output> = 
    abstract member MyFun: 'input -> 'output 

type MyClass() = 
    interface MyInterface<string, unit> with 
     member this.MyFun(input: string) =() 
    //fails with error FS0017: The member 'MyFun : string -> unit' does not have the correct type to override the corresponding abstract method. 
type MyUnit = MyUnit 
type MyClass2() = 
    //success 
    interface MyInterface<string, MyUnit> with 
     member this.MyFun(input: string) = MyUnit 

Antwort

15

Das sieht aus wie ein böse Ecke Fall in der # Sprache F, aber ich bin nicht sicher, ob es als Neben Design-Einschränkung oder einen Fehler in dem Compiler qualifiziert. Wenn es sich um eine Designbeschränkung handelt, sollte die Fehlermeldung dazu führen, dass (weil es momentan keinen Sinn macht).

Wie auch immer, das Problem ist, dass der F # -Compiler keinen Code generiert, der tatsächlich den unit-Typ in der IL enthält. Sie ersetzt sie durch void (wenn sie als Rückgabetyp verwendet wird) oder durch eine leere Argumentliste (wenn sie als Methoden- oder Funktionsargument verwendet wird).

Das bedeutet, dass in dem MyClass Typ, der Compiler das MyFun Mitglied als Methode zu kompilieren entscheiden die string nimmt und void (aber man kann nicht void als generisches Typargument verwenden, so dass dies einfach nicht funktioniert). Im Prinzip könnte der Compiler in diesem Fall den tatsächlichen unit-Typ verwenden (weil das der einzige Weg ist, um es zum Laufen zu bringen), aber das würde wahrscheinlich an anderer Stelle andere Inkonsistenzen erzeugen.

Ihr Trick mit der Erstellung MyUnit ist, denke ich, eine vollkommen gute Möglichkeit, das Problem zu lösen. Sogar die Kern-F # -Bibliothek verwendet an einigen Stellen der Implementierung (in asynchronen Workflows) etwas wie MyUnit, um mit einigen Einschränkungen von unit (und der Art, wie es kompiliert wird) umzugehen.

+0

Danke Tomas. Ich habe dieses Problem nirgendwo anders gesehen (z. B. in normalen Funktionen mit Let;) –

+0

@Stefan: Wenn Sie den Typ "Einheit" als Argument (zu einer Funktion oder einem Typ) verwenden, dann ist es im Allgemeinen gut. Dieser Fehler/Einschränkung erscheint wahrscheinlich nur bei der Implementierung abstrakter Mitglieder (was ein bisschen knifflige Bereich für den F # -Compiler ist, weil Vererbung ist überraschend komplex in .NET) –

+1

Interessanterweise wird es in C# funktionieren und ich kann die Funktion in F # verbrauchen. Wahrscheinlich sollte als ein Fehler gemeldet werden. –

Verwandte Themen