F# 如何声明保留度量单位的通用转换运算符?

F# 如何声明保留度量单位的通用转换运算符?,f#,F#,F#中的内置转换运算符消除了度量单位。我想定义那些保存它们的。对于一个特定的转换,我可以做得很好,例如int到float: let inline intToFloat (x:int<'u>) = x |> float |> LanguagePrimitives.FloatWithMeasure<'u> 让内联intToFloat(x:int 但我不知道泛型((任何带有op_Implicit ^m->float)->float)运算符的语法是什么:

F#中的内置转换运算符消除了度量单位。我想定义那些保存它们的。对于一个特定的转换,我可以做得很好,例如int到float:

let inline intToFloat (x:int<'u>) =
    x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
让内联intToFloat(x:int
但我不知道泛型((任何带有op_Implicit ^m->float)->float)运算符的语法是什么:

let inline floatM (x:^m<'u>) =
    x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
// FS0712: Type parameter cannot be used as type constructor
让内联floatM(x:^m
//FS0712:类型参数不能用作类型构造函数
有可能这样做吗?

我就是这样做的:

let inline toIntWithMeasure<[<Measure>] 'a> (x:obj) =
  match x with
  | :? int as i -> i |> LanguagePrimitives.Int32WithMeasure<'a>
  | _ -> failwith "Not an int!"
让内联toIntWithMeasure
|->failwith“Not a int!”

解决方法是使用重载而不是泛型:

type Conv =
    static member inline toDouble<[<Measure>] 'u> (x: float32<'u>) = 
        x |> float |> LanguagePrimitives.FloatWithMeasure<'u>

    static member inline toDouble<[<Measure>] 'u> (x: sbyte<'u>) = 
        x |> float |> LanguagePrimitives.FloatWithMeasure<'u>

    static member inline toDouble<[<Measure>] 'u> (x: int16<'u>) = 
        x |> float |> LanguagePrimitives.FloatWithMeasure<'u>

    static member inline toDouble<[<Measure>] 'u> (x: int<'u>) = 
        x |> float |> LanguagePrimitives.FloatWithMeasure<'u>

    static member inline toDouble<[<Measure>] 'u> (x: int64<'u>) = 
        x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
type Conv=
静态成员内联(双重)=
x |>float |>LanguagePrimitives.FloatWithMeasure(x:sbyte
静态成员内联(双重)=
x |>float |>LanguagePrimitives.FloatWithMeasure(x:int
静态成员内联(双重)=

x |>float |>language primitives.FloatWithMeasure->float我想答案是否定的,因为F#type系统不能表达更高级的类型。我不再使用度量单位。F#缺少HKT的元原因是很难使用它们。我遇到的一个具体例子是,不久前我尝试用单位来建模货币。这就是在我的库的调用站点上导致了一些严重的代码膨胀,因为我必须为每个单元实例化类型和代码。我当时切换到DU。有一些其他缺点,但毕竟更容易
let f = Conv.toDouble (45<second>) // f is a float<second>
let inline floatM< ^m, [<Measure>]'u when (^m) : (static member toFloat: ^m<'u> -> float<'u>)> (x:^m) =
    Conv.toDouble x