带私有构造函数的F#struct声明

时间:2014-11-06 08:20:03

标签: f#

假设我们有一个AngularSpeed类,它包含角度,速度和时间(速度=角度/时间)。显然,一次设置所有三个值是不明确的。所以我们使用私有构造函数和静态函数从(速度,时间)或(角度,时间)创建AngularSpeed

[<Struct>]
type AngularSpeed private (angle: float, speed: float, time: float) =

    member x.Angle = angle
    member x.Time = time
    member x.Speed = speed

    static member FromAngleTime(angle, time) = AngularSpeed(angle, angle/time, time)
    static member FromSpeedTime(speed, time) = AngularSpeed(time*speed, speed, time)

该示例有效。但是如果没有[Struct],我就无法创建相同的结构,但是使用&#39;&#39; struct ... end&#39;&#39;关键字。那么,如何使用&#39;&#39; struct ... end&#39;&#39;?有可能吗?

type AngularSpeed  =
    struct
      ...
    end

2 个答案:

答案 0 :(得分:4)

我认为使用[<Struct>]和主要构造函数的定义通常是首选(至少,它看起来更好!)但我相信使用struct .. end的以下定义等同于您正在做的事情:

type AngularSpeed = struct
  val mutable angle : float
  val mutable speed : float
  val mutable time : float
  private new (angle: float, speed: float, time: float) =
    { angle = angle; time = time; speed = speed }
  static member FromAngleTime(angle, time) = AngularSpeed(angle, angle/time, time)
  static member FromSpeedTime(speed, time) = AngularSpeed(time*speed, speed, time)
end

我想最棘手的是构造函数体的语法 - 而不是使用变量分配值,F#使用类似记录的语法来初始化字段。

答案 1 :(得分:3)

我没有看到struct...end语法使用得多,但直接重新制定看起来像这样(这种类型的名称很奇怪,见下文):

type AngularSpeed =
    struct
        val Angle : float
        val Speed : float
        val Time : float
    end

    private new (angle, speed, time) =
        { Angle = angle; Speed = speed; Time = time }

    static member FromAngleTime(a, t) = AngularSpeed(a, a/t, t)
    static member FromSpeedTime(s, t) = AngularSpeed(s*t, s, t)

请注意,无论语法如何,任何像这样的结构都会有一个空构造函数,将所有值都设置为Unchecked.defaultof<_>

方法变体

该结构冗余地存储数据;角度可以是一个成员。此外,您正在使用物理单位;您可能想要使用度量单位。按原样,我不明白这种类型是什么。我不希望角速度包含时间或角度,而是如果你更喜欢以度为单位的角度,它将是float</s>float<deg/s>。也许这种类型应该被称为RotationProcess或类似的东西?

/// Time in seconds. Abbreviation for the Microsoft standardized type.
[<Measure>] type s = Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols.s

type RotationProcess =
    struct
        val Speed : float</s>
        val Time : float<s>
    end

    member rp.Angle = rp.Speed * rp.Time
    private new (s, t) = { Speed = s; Time = t }
    static member FromAngleTime(a, t) = RotationProcess(a/t, t)
    static member FromSpeedTime(v, t) = RotationProcess(v, t)
    static member FromAngleSpeed(a, v) = RotationProcess(v, a/v)