假设我定义了一个模块来处理带有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.0<m>
),这可能吗?声明m
my_var : Vector3<m>
是否可以隐含地导出{{1}}
答案 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<_>)