.net 带度量单位的重载函数

.net 带度量单位的重载函数,.net,generics,f#,.net,Generics,F#,TL;DR如何编写一个“重载”函数来处理所有带单位的数字类型和一个带相同单位的单独类型(float32->Vector2,int->Vector2) 我有一个很好的小Vector2类,但我想允许将度量单位附加到它,所以我基本上是这样定义的(但功能比这里包含的多得多): 到目前为止,我已经编写了一个帮助器类来处理这个问题: type OverloadedOperators = static member CreateVector2 (x: float32<'u>, y: flo

TL;DR如何编写一个“重载”函数来处理所有带单位的数字类型和一个带相同单位的单独类型(
float32->Vector2
int->Vector2

我有一个很好的小Vector2类,但我想允许将度量单位附加到它,所以我基本上是这样定义的(但功能比这里包含的多得多):

到目前为止,我已经编写了一个帮助器类来处理这个问题:

type OverloadedOperators =
    static member CreateVector2 (x: float32<'u>, y: float32<'u>) = new Vector2<'u>(x, y)
    static member CreateVector2 (x: float<'u>, y: float<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)
    static member CreateVector2 (x: int<'u>, y: int<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)
类型重载运算符=
静态成员CreateVector2(x:float32)=新向量2,y:float(x |>float32 |>Float32WithMeasure)

静态成员CreateVector2(x:int)=new Vector2,y |>float32 |>Float32WithMeasure Vector2如何
让内联(@@@)(x:float32)=new Vector2这里有一个略显粗糙的解决方案,它是根据我们在这种情况下使用的标准技巧构建的:

open LanguagePrimitives
type Vector2<[<Measure>] 'u>(x: float32<'u>, y: float32<'u>) =
    member this.X = x
    member this.Y = y
type OverloadedOperators() =
    static member CreateVector2 (x: float32<'u>, y: float32<'u>) = new Vector2<'u>(x, y)
    static member CreateVector2 (x: float<'u>, y: float<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)
    static member CreateVector2 (x: int<'u>, y: int<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)
    static member ( *** ) (T,(x:float32<'u>,y)) = OverloadedOperators.CreateVector2(x,y)
    static member ( *** ) (T,(x:float<'u>,y)) = OverloadedOperators.CreateVector2(x,y)
    static member ( *** ) (T,(x:int<'u>,y)) = OverloadedOperators.CreateVector2(x,y)
let convert  =OverloadedOperators() 

(* testing *)
[<Measure>]
type m

convert *** (1<m>,1<m>)
convert *** (1.0<m>,1.0<m>)
openlanguageprimitives
类型向量2,y:float32,y:float32(x,y)
静态成员CreateVector2(x:float)=新向量2,y |>float32 |>Float32WithMeasure,y:int(x |>float32 |>Float32WithMeasure)
静态成员(***)(T,(x:float32,y))=重载运算符。CreateVector2(x,y)

静态成员(***)(T,(x:int我能够从@JohnPalmer的答案开始走到最后一英里;只是对我没有想到的类型签名进行了一个简单的更改。这里是第一部分:

type OverloadedOperators() =
    static member CreateVector2 (_, x: float32<'u>, y: float32<'u>) = new Vector2<'u>(x, y)
    static member CreateVector2 (_, x: float<'u>, y: float<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)
    static member CreateVector2 (_, x: int<'u>, y: int<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)

let ops = new OverloadedOperators()
类型重载运算符()=
静态成员CreateVector2(124;,x:float32)=新向量2,y:float(x |>float32 |>Float32WithMeasure)
静态成员CreateVector2(124;,x:int)=新向量2,y |>float32 |>Float32WithMeasure)(ops,x,y))

因此,我们有了它:成功的运算符重载,可用于任何数字类型和度量单位。

这是我们能得到的最接近的值吗?:)
let inline (@@) (x: 'u when 'u : (static member CreateVector2 : 'u * 'u -> Vector2<'v>)) y = OverloadedOperators.CreateVector2 (x, y)
open LanguagePrimitives
type Vector2<[<Measure>] 'u>(x: float32<'u>, y: float32<'u>) =
    member this.X = x
    member this.Y = y
type OverloadedOperators() =
    static member CreateVector2 (x: float32<'u>, y: float32<'u>) = new Vector2<'u>(x, y)
    static member CreateVector2 (x: float<'u>, y: float<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)
    static member CreateVector2 (x: int<'u>, y: int<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)
    static member ( *** ) (T,(x:float32<'u>,y)) = OverloadedOperators.CreateVector2(x,y)
    static member ( *** ) (T,(x:float<'u>,y)) = OverloadedOperators.CreateVector2(x,y)
    static member ( *** ) (T,(x:int<'u>,y)) = OverloadedOperators.CreateVector2(x,y)
let convert  =OverloadedOperators() 

(* testing *)
[<Measure>]
type m

convert *** (1<m>,1<m>)
convert *** (1.0<m>,1.0<m>)
type OverloadedOperators() =
    static member CreateVector2 (_, x: float32<'u>, y: float32<'u>) = new Vector2<'u>(x, y)
    static member CreateVector2 (_, x: float<'u>, y: float<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)
    static member CreateVector2 (_, x: int<'u>, y: int<'u>) = new Vector2<'u>(x |> float32 |> Float32WithMeasure<'u>, y |> float32 |> Float32WithMeasure<'u>)

let ops = new OverloadedOperators()
let inline (@@) (x: ^a) (y: ^b) = ((^T or ^a or ^b) : (static member CreateVector2 : ^T * ^a * ^b -> Vector2<'u>) (ops, x, y))