Search code examples
f#symbolic-mathcomputer-algebra-systemssymbolic-computation

C# library overloads ^ operator. How to use ** instead?


The Symbolism library overloads arithmetic operators. Although it's written in C# I can use it from F#:

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)

the output:

3 + 6 * x + 13 * y + z

However, it also overloads ^ for powers. This of course doesn't play well with F#.

As a step towards a workaround, I exported a method group for powers:

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

output:

x ^ 3

How can I overload ** to use the Aux.Pow method group instead?

I can do something like this:

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

And that does work for MathObject values:

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

But Aux.Pow is overloaded for int as well:

    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 suggestions welcome!


Solution

  • You can use the trick described here like this:

    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
    

    Unlike in the linked answer, we have to use the (?<-) operator because it's the only operator that can take 3 arguments instead of 2, and we need to overload on both the left and right side of the ^ operator