F#中的通用单位

时间:2015-02-28 21:12:40

标签: generics f# units-of-measurement

在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取代。有可能吗?

1 个答案:

答案 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。