Asik
Asik

Reputation: 22133

How to use overloaded explicit conversion operators?

I have a type defined in C# like this:

struct F {
    public static explicit operator F(long value) {}
    public static explicit operator long(F value) {}
    public static explicit operator F(double value) {}
    public static explicit operator double(F value) {}
    // more conversion operators
}

In F# if I want to create it from a long, the only way I found is:

let l = F.op_Explicit 3L

I tried creating an inline function to make this nicer:

let inline f a = F.op_Explicit a

But this doesn't compile. I also tried with a member constraint:

let inline f (x:^a) = (F: (static member op_Explicit : ^a -> F) x) 

And that doesn't compile either.

Is it possible to define a function or operator to choose the right overload?

On a side note, it does work nicely in the opposite direction:

let f = someF |> int64 // calls the right conversion operator

Upvotes: 7

Views: 500

Answers (1)

kvb
kvb

Reputation: 55184

It's not valid to have a member constraint on a single concrete type; however, this might work for you:

let inline f (x:^a) : F =
    let inline g x = ((^b or ^c):(static member op_Explicit : ^b -> ^c) x)
    g x

This has the more general type f : ^a -> F when ( ^a or F) : (static member op_Explicit : ^a -> F), which is a type that is impossible to manually annotate any value with!

Upvotes: 6

Related Questions