Библиотека C# перегружает оператор ^. Как использовать ** вместо этого?

Библиотека Symbolism перегружает арифметические операторы. Хотя он написан на C#, я могу использовать его из 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)

выход:

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

Любые предложения приветствуются!

2 ответа

Решение

Вы можете использовать описанный здесь трюк следующим образом:

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, и нам нужно перегрузить как левую, так и правую часть оператора ^

Вот тот же ответ, но без операторов. Это работает только в 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)
Другие вопросы по тегам