简化F#中的记录分配

时间:2011-11-23 11:19:11

标签: f# record measure

假设我定义了一个模块来处理带有F#中度量单位的向量:

module Vec

    [<Measure>]
    type m

    type Vector3<[<Measure>] 'a> =
        {
        X : float<'a>
        Y : float<'a>
        Z : float<'a>
        }

现在我想创建一个let持有Vector3的变量。我可以这样做:

let my_var : Vector3<m> = {X = 1.0<m> ; Y = 1.0<m> ; Z = 1.0<m>};

我必须做很多像上面那样的任务,所以我想知道,有没有办法简化以前的语法?类似的东西:

let my_var : Vector3<m> = { 1.0,1.0,1.0} //this don't compile
let my_var : Vector3<m> = {1.0<m> ; 1.0<m> ; 1.0<m>} //this don't compile either

我想:

  1. 避免度量单位规范(1.0<m>),这可能吗?声明m
  2. 中的my_var : Vector3<m>是否可以隐含地导出{{1}}
  3. 避免使用记录字段名称(如第二个示例中所示)。编译器本身是否可以根据订单派生记录的字段名称?

2 个答案:

答案 0 :(得分:5)

我认为您不需要自己为变量指定类型,让F#进行类型推断。所以下面的声明就足够了:

let my_var = {X = 1.0<m> ; Y = 1.0<m> ; Z = 1.0<m>}

如果您不想指定记录字段名称(我认为很好地使您的程序清晰),您可以将记录更改为类(如@ Tarmil的答案)或不相交的联合。就个人而言,我更喜欢不相交的工会,因为我仍然可以轻松地在模式匹配中使用它们:

type Vector3<[<Measure>] 'a> = Vector3 of float<'a> * float<'a> * float<'a>

let my_var1 = Vector3(1.0, 1.0, 1.0) // Vector3<1>
let my_var2 = Vector3(1.0<m>, 1.0<_>, 1.0<_>) // Vector3<m>

答案 1 :(得分:4)

  

避免测量单位规格(1.0),这可能吗?是不是可以从声明my_var:Vector3?

中隐含地推导出来

实际上,1.0相当于1.0&lt; 1&gt;,因此您不能在期望非1(无量纲)的度量的上下文中使用它。

但是,您可以使用1.0&lt; _&gt;。

来使用推理
  

避免使用记录字段名称(如第二个示例中所示)。编译器本身是否可以根据顺序派生记录的字段名称?

我能想到的最接近的事情如下:

type Vector3<[<Measure>] 'a> =
    val X : float<'a>
    val Y : float<'a>
    val Z : float<'a>
    new(x, y, z) = { X = x; Y = y; Z = z }

然后可以这样使用:

let my_var = Vector3<m>(1.0<_>, 1.0<_>, 1.0<_>)