6

Symbolism庫重載算術運算符。雖然它寫在C#我可以從F#使用它:C#庫重載^運算符。如何使用**代替?

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) 

輸出:

3 + 6 * x + 13 * y + z 

然而,它也重載^的權力。這當然不適合F#。

作爲朝着解決辦法了一步,我出口爲列強的方法組:

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

輸出:

x^3 

我如何能超載**使用Aux.Pow方法組呢?

我可以做這樣的事情:

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

而且,做工作MathObject值:

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

Aux.Pow目前超載int還有:

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

任何建議歡迎!

+0

你不能用其他操作數類型聲明相同的函數嗎? – 2013-03-11 16:12:30

+0

嗨@JonSkeet。我不認爲F#操作符(函數)會重載C#方法的方式。這是你的意思嗎? – dharmatech 2013-03-11 23:47:31

回答

10

可以使用的伎倆描述here這樣的:

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 

不像在鏈接的答案,我們必須使用 - 運營商,因爲它是可以採取3個參數,而不是唯一的運營商(<?) 2,並且我們需要在^運算符的左側和右側超載

+0

謝謝古斯塔沃! – dharmatech 2013-03-11 23:35:38

+0

我一直在使用你的'$'技巧一段時間了,我很好奇 - 你怎麼知道'?< - ',並且在這裏它是必要/合適的?只需注意語言規範中的細節? – ildjarn 2013-03-12 18:38:48

+0

我從另一個我鏈接的stackoverflow問題中學到了'$'技巧,然後我需要一個額外的參數,並且我記得?< - 使用了3個參數而不是2個。我去了MSDN文檔以查看是否有另一個參數,但似乎沒有 – 2013-03-12 19:37:43

5

以下是相同的答案,但沒有運算符。 它僅適用於F#3.0,您可以使用任意數量的參數。

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)