2

假设我在 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隐含地从声明中推导出来的 my_var : Vector3<m>吗?
  2. 避免使用记录字段名称(如第二个示例)。记录的字段名不是由编译器自己根据顺序推导出来的吗?
4

2 回答 2

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>
于 2011-11-23T12:05:52.870 回答
4

避免测量单位规范(1.0),这可能吗?m 不是可以从声明 my_var : Vector3 中隐式推导出来的吗?

实际上,1.0 等价于 1.0<1>,因此您不能在预期 1(无量纲)以外的度量的上下文中使用它。

但是,您可以通过使用 1.0<_> 来使用推理。

避免使用记录字段名称(如第二个示例)。记录的字段名不是由编译器自己根据顺序推导出来的吗?

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

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<_>)
于 2011-11-23T11:41:25.470 回答