6

La libreria Symbolism sovraccarica gli operatori aritmetici. Anche se è scritto in C# posso usarlo da F #:Sovraccarico di librerie C# operatore. Come usare ** invece?

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) 

l'output:

3 + 6 * x + 13 * y + z 

Tuttavia, sovraccarica anche ^ per potenze. Questo ovviamente non funziona bene con F #.

Come un passo verso una soluzione, ho esportato un gruppo di metodo per potenze:

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

uscita:

x^3 

Come posso sovraccaricare ** di utilizzare il gruppo Aux.Pow metodo, invece?

posso fare qualcosa di simile:

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

E questo funziona per MathObject valori:

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

Ma Aux.Pow è sovraccarico per int così:

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; } 

Eventuali suggerimenti benvenuto!

+0

Non si possono dichiarare le stesse funzioni con gli altri tipi di operandi? –

+0

Ciao @JonSkeet. Non credo che gli operatori di F # (funzioni) sovraccarichino il modo in cui i metodi C# fanno. E 'questo che intendevi? – dharmatech

risposta

10

È possibile utilizzare il trucco descritto here come questo:

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 

differenza nella risposta legata, dobbiamo usare l'operatore - perché è l'unico operatore che può prendere 3 argomenti invece di (<?) 2, e abbiamo bisogno di sovraccaricare sia il lato sinistro che quello destro dell'operatore^

+0

Grazie Gustavo! – dharmatech

+0

Sto usando il tuo trucco '$' da un po 'di tempo, e sono curioso - come facevi a sapere di '? <-', e che era necessario/appropriato qui? Solo attenzione ai dettagli nelle specifiche della lingua? – ildjarn

+0

Ho imparato il trucco '$' dall'altra domanda di stackoverflow che ho collegato, e quindi avevo bisogno di un parametro aggiuntivo e mi sono ricordato? <- ho preso 3 argomenti invece di 2. Sono andato al documento MSDN per vedere se ce n'era un altro, ma sembra che non ci sia –

5

Ecco la stessa risposta ma senza operatori. Funziona solo in F # 3.0 ed è possibile utilizzare qualsiasi numero di parametri.

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)