在F#中编写泛型函数时,我可以使用LanguagePrimitives模块中定义的成员,例如在这个函数中,只是递增一个数字
let inline increment (x : 'a) =
x + LanguagePrimitives.GenericOne
我想知道是否有类似于计量单位的工作。特别是:是否可以编写一个带有泛型参数的函数,并将其转换为具有单位的相同类型的数字。类似的东西:
let inline toNumberWithUnit<[<Measure>] 'u> x =
x * GenericOne<'u> //that won't work
这将有一个类型:'a - &gt; 'A&LT;' U取代。有可能吗?
答案 0 :(得分:2)
该签名在.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。
<强>更新强>
过了一段时间我也遇到了这种情况,发现这个答案恰好来自我:)
在尝试使用不同的度量单位之后,我意识到它不起作用,因为类型推断并没有对度量单位进行推广,所以发布的示例有效,因为类型推断见证了{{{ 1}}测量然后专注于M
上的函数。
然而,通过明确使用上面定义的M
运算符,这是一种使其有效的方法:
$
可能有一种方法可以创建泛型函数或泛型常量,但目前使用当前版本的F#似乎无法实现。
我会尝试使用F#4.1。