6

Die Bibliothek Symbolism überlastet arithmetische Operatoren. Obwohl es in C# geschrieben ist kann ich es von F # verwenden:C# -Bibliothek überlastet den Operator ^. Wie benutze ich stattdessen **?

open Symbolism 

let x = new Symbol("x") 
let y = new Symbol("y") 
let z = new Symbol("z") 

printfn "%A" (2*x + 3 + 4*x + 5*y + z + 8*y) 

die Ausgabe:

3 + 6 * x + 13 * y + z 

Es ist jedoch Überlastungen auch ^ für Kräfte. Dies spielt natürlich nicht gut mit F #.

Als Schritt in Richtung auf dieses Problem zu umgehen, exportierte ich eine Methode Gruppe für Kräfte:

printfn "%A" (Aux.Pow(x, 2) * x) 

Ausgang:

x^3 

Wie ich ** überlasten können stattdessen die Aux.Pow Methodengruppe zu bedienen?

Ich kann etwas tun:

let (**) (a: MathObject) (b: MathObject) = Aux.Pow(a, b) 

Und das funktioniert für MathObject Werte:

> x ** y * x;; 
val it : MathObject = x^(1 + y) 

Aber Aux.Pow ist für int auch überlastet:

public static MathObject Pow(MathObject a, MathObject b) 
    { return new Power(a, b).Simplify(); } 

    public static MathObject Pow(MathObject a, int b) 
    { return a^new Integer(b); } 

    public static MathObject Pow(int a, MathObject b) 
    { return new Integer(a)^b; } 

Any Vorschläge willkommen!

+0

Können Sie nicht die gleichen Funktionen mit den anderen Operandentypen deklarieren? –

+0

Hallo @ JonSkeet. Ich glaube nicht, dass F # -Operatoren (Funktionen) die Art von C# -Methoden überladen. Ist es das, was du meintest? – dharmatech

Antwort

10

Sie den Trick verwenden können, beschrieben here wie folgt aus:

open Symbolism 

type MathObjectOverloads = 
    | MathObjectOverloads 
    static member (?<-) (MathObjectOverloads, a: #MathObject, b: int) = MathObject.op_ExclusiveOr(a, b) 
    static member (?<-) (MathObjectOverloads, a: #MathObject, b: #MathObject) = MathObject.op_ExclusiveOr(a, b) 
    static member (?<-) (MathObjectOverloads, a: System.Int32, b: #MathObject) = MathObject.op_ExclusiveOr(a, b) 

let inline (**) a b = (?<-) MathObjectOverloads a b 

let two = Integer(2) 
let three = Integer(3) 

two ** three 

two ** 3 

2 ** three 

Anders als in der verknüpften Antwort, müssen wir das nutzen - Betreiber, weil es der einzige Betreiber ist, die drei Argumente können statt (<?) 2, und wir müssen auf der linken und rechten Seite des^-Operators überladen

+0

Danke Gustavo! – dharmatech

+0

Ich benutze deinen '$' Trick schon seit einiger Zeit, und ich bin neugierig - woher weißt du von '? <-', und dass es hier notwendig/angemessen war? Nur auf Details in der Sprachspezifikation achten? – ildjarn

+0

Ich habe den '$' Trick von der anderen stackoverflow Frage gelernt, die ich verlinkt habe, und dann brauchte ich einen zusätzlichen Parameter und ich erinnerte mich? <- nahm 3 Argumente anstelle von 2. Ich ging zu den MSDN-Dokumenten, um zu sehen, ob es noch einen gab. aber es scheint, gibt es nicht –

5

Hier ist die gleiche Antwort, aber ohne Betreiber. Es funktioniert nur in F # 3.0 und Sie können eine beliebige Anzahl von Parametern verwenden.

let inline i3 (a:^a,b:^b,c:^c) = ((^a or ^b or ^c) : (static member threeParams: ^a* ^b* ^c -> _) (a,b,c)) 

open Symbolism 

type MathObjectOverloads = 
    | MathObjectOverloads 
    static member threeParams (MathObjectOverloads, a: #MathObject , b: int  ) = MathObject.op_ExclusiveOr(a, b) 
    static member threeParams (MathObjectOverloads, a: #MathObject , b: #MathObject) = MathObject.op_ExclusiveOr(a, b) 
    static member threeParams (MathObjectOverloads, a: System.Int32, b: #MathObject) = MathObject.op_ExclusiveOr(a, b) 

let inline (**) a b = i3(MathObjectOverloads, a, b) 
Verwandte Themen