2011-03-11 34 views
2

我需要能够用F#中的几个不同单位表示相同的概念。例如,我想用光年,天文单位,公里和米表示“距离”。我想使用通用函数来计算这些值。这是我一直LY分组,AU,公里,和m在一起:为什么这个度量单位被限制为1?

[<Measure>] type ly 
[<Measure>] type AU 
[<Measure>] type km 
[<Measure>] type m 

[<Measure>] type distance 

type UnitValue<[<Measure>] 'u, [<Measure>] 't> = 
    val conversionFactor : float<'t/'u> 
    val value : float<'u> 
    new (v, cf) = { value = FloatWithMeasure<'u> v; conversionFactor = FloatWithMeasure<'t/'u> cf } 
    member this.toUnits = this.value * this.conversionFactor 
    member this.fromUnits (x : float<'t>) = x/this.conversionFactor 
    static member (+) (a : UnitValue<'u, 't>, b : UnitValue<_, 't>) = 
     a.newValue (a.toUnits + b.toUnits) 
    static member (-) (a : UnitValue<'u, 't>, b : UnitValue<_, 't>) = 
     a.newValue (a.toUnits - b.toUnits) 
    static member (*) (a : UnitValue<'u, 't>, b : float) = 
     a.newValue (a.toUnits * b) 
    member this.newValue (x : float<'t>) = 
     new UnitValue<'u, 't>(float (this.fromUnits x), float this.conversionFactor) 

//Distance units 
type LightYearValue(value) = 
    inherit UnitValue<ly, distance>(value, 6324.0) 

type AstronomicalUnitValue(value) = 
    inherit UnitValue<AU, distance>(value, 15.0) 

type KilometerValue(value) = 
    inherit UnitValue<km, distance>(value, 0.00001) 

type MeterValue(value) = 
    inherit UnitValue<m, distance>(value, 0.0000000) 

此代码是从单位不知道C#调用,而且可以通过指定new LightYearValue(4.2),这将在F#成为UnitValue<ly, distance>完成,并且可以传递给期望UnitValue<_, distance>的函数。这样,适当的单位进入功能,并适当的单位出去。例如,如果我通过函数a UnitValue<AU, distance>,根据计算结果我可能会得到一个float<AU/s^2> - 并且它将是该比例的适当数字。

感觉与此很高兴,我开始写作的轨道类型:

and Orbit(PeR : UnitValue<_, distance>, ApR : UnitValue<_, distance>, AgP : float, focus : SphericalMass) = 
    let PeR = PeR 
    let ApR = ApR 
    let AgP = AgP 
    let focus = focus 
    let Maj = PeR + ApR 
    let Ecc = (Maj.value - (2.0 * PeR.value))/Maj.value 
    let DistanceAt theta = 
     (Maj.value/2.0) * (1.0 - Ecc ** 2.0)/(1.0 + Ecc * Math.Cos(theta)) 

,但是当我将鼠标悬停我的鼠标PeR,它说,它的类型是UnitValue<1, distance>。那么是什么给了?为什么这不起作用?我可以编写一个功能为UnitValue<_, distance>,它工作正常!它可能与C#与这些代码交互吗? (类型由一个C#类扩展)有什么办法,使这项工作:(

回答

3

当声明类型,你需要声明泛型参数(也机组参数)明确,下面的声明推断类型正确:

type Orbit<[<Measure>] 'u, [<Measure>] 'v> 
    (PeR : UnitValue<'u, distance>, ApR : UnitValue<'v, distance>, 
     AgP : float, focus : SphericalMass) = 
    let Maj = PeR + ApR 
    let Ecc = (Maj.value - (2.0 * PeR.value))/Maj.value 
    let DistanceAt theta = 
     (Maj.value/2.0) * (1.0 - Ecc ** 2.0)/(1.0 + Ecc * Math.Cos(theta)) 

(顺便说一句:你不需要重新分配参数,以当地let绑定 - 他们会自动被访问,所以我删除喜欢let ApR = ApR线)!当然

+0

我是那种但是我害怕:/我不想在任何地方宣布单位 – 2011-03-11 14:55:35