2011-08-22 63 views
9

撇开我们是否应该使用的测量单位,像角无单位的概念,假设我有定义degreeradian单位在F#如何在F#计量单位上定义扩展成员?

type [<Measure>] degree = 
    static member ToRadians (d:float<degree>) : float<radian> = d * (Math.PI * 1.<radian>)/180.0<degree> 
and [<Measure>] radian = 
    static member ToDegrees (r:float<radian>) : float<degree> = r * 180.0<degree>/(Math.PI * 1.<radian>) 

我可以比较轻松地使用他们喜欢

4.0<degree> |> degree.ToRadians 

似乎像扩展成员会更加轻松。所以我还是说

let d = 4.0<degree> 
let r = d.ToRadians() 

但我不能确定延长部件的明显的方式

type float<degree> with 
    member degrees.ToRadians() = degree.ToRadians(degrees) 

...这让我下面的错误

error FS0010: Unexpected identifier in type name. Expected infix operator, quote symbol or other token. 

是否有F#中度量单位的扩展成员的语法技巧,还是支持的功能?

+0

我会冒险猜测它不被支持。我试过的所有东西都给出了错误:'度量声明可能只有静态成员'。 – Daniel

+1

问题是编译后删除了度量类型信息,所以在运行时一切都只是一个'float',因此调用一个实例方法没有意义 –

+1

@jpalmer。在编译期间,扩展成员是静态解析的。 –

回答

5

F#扩展成员与C#扩展成员不同,因为您无法定义构造的泛型类型的扩展。例如,您可以在seq<'t>而不是seq<int>上定义扩展名。换句话说,扩展成员的行为类似于类型的成员,而不是静态方法。这适用于测量类型的,所以你不能在float<degree>定义一个扩展,但你可以在float<[<Measure>]'u>定义一个扩展:

type float<[<Measure>]'u> with 
    member f.Squared() = f * f 

[<Measure>] 
type m 

let area = 2.0<m>.Squared() 

不过,我看不出这可以帮助你在你的情况..

+0

这很有道理。除了定义语法之外,定义这些扩展方法并没有真正的好处,还有很多其他的好选择。 –