该签名在 .NET 中是非法的,因此唯一的方法是使用带有静态约束的 F# 内联功能。
然后你可以这样定义一个函数:
[<Measure>]
type M = class end
let x = LanguagePrimitives.FloatWithMeasure<M> 2.
type T<[<Measure>]'M>() =
static member ($) (T, x) = LanguagePrimitives.FloatWithMeasure<'M> x
static member ($) (T, x) = LanguagePrimitives.Float32WithMeasure<'M> x
static member ($) (T, x) = LanguagePrimitives.Int32WithMeasure<'M> x
// more overloads
let inline NumberWithMeasure x = T() $ x
let a: float<M> = NumberWithMeasure 2.
let b: float32<M> = NumberWithMeasure 2.0f
let c: int<M> = NumberWithMeasure 2
处理泛型数字和度量单位时的主要问题是,您最终会得到那些具有泛型类型和类型参数(higher kind)的签名,目前 .NET 不支持这些签名.
更新
过了一会儿,我也遇到了这种情况,发现这个答案恰好来自我:)
在尝试使用不同的度量单位后,我意识到它不起作用,因为类型推断不能概括度量单位,发布的示例有效,因为类型推断见证了 M 度量的使用,然后专门针对M 的函数。
但是,通过显式使用上面定义的$ 运算符,这是一种使其工作的方法:
[<Measure>] type km
[<Measure>] type miles
type WithMeasure<[<Measure>]'M>() =
static member ($) (x, T) = LanguagePrimitives.FloatWithMeasure<'M> x
static member ($) (x, T) = LanguagePrimitives.Float32WithMeasure<'M> x
static member ($) (x, T) = LanguagePrimitives.Int32WithMeasure<'M> x
static member ($) (x, T) = LanguagePrimitives.DecimalWithMeasure<'M> x
static member ($) (x, T) = LanguagePrimitives.Int16WithMeasure<'M> x
static member ($) (x, T) = LanguagePrimitives.Int64WithMeasure<'M> x
static member ($) (x, T) = LanguagePrimitives.SByteWithMeasure<'M> x
// no more overloads
let a: float<km> = 2. $WithMeasure()
let b: float32<miles> = 2.0f $WithMeasure()
可能有一种方法可以创建泛型函数或泛型常量,但目前似乎无法使用当前版本的 F#。
我会在 F# 4.1 准备好后尝试它。