F# 测量单位:从弧度到速度(米/秒)
假设我已经定义了一个用于处理 3 维向量和测量单位的 F# 模块:
[<Measure>]
type m
[<Measure>]
type s
[<Measure>]
type v = m/s
[<Measure>]
type rad
type Vector3<[<Measure>] 'a> =
{
X : float<'a>
Y : float<'a>
Z : float<'a>
}
在某处我有一个以弧度表示的角度:
let angle:float32<rad> = 0.5f<rad>
现在我必须声明一个 Vector3(速度),使用该角度来计算其分量。我尝试了类似的方法:
let velocity : Vector3<m/s> = { X = Math.Cos(angle);Y = Math.Sin(angle);Z = 0.0<m/s>} //don't compile
上面的代码无法编译,因为 Vector3 需要 X 和 Y 中的值,但 Sin 返回一个浮点数。
我该如何解决这个问题?如果可能的话,我想在测量单位之间执行转换,而不是强制转换,这样编译器就可以保证我在将角度转换为速度时做正确的事情。
有什么建议吗?
let's say I've defined an F# module for handling 3-dimensional vectors and measure unit:
[<Measure>]
type m
[<Measure>]
type s
[<Measure>]
type v = m/s
[<Measure>]
type rad
type Vector3<[<Measure>] 'a> =
{
X : float<'a>
Y : float<'a>
Z : float<'a>
}
And somewhere I have an angle expressed in radians:
let angle:float32<rad> = 0.5f<rad>
Now I have to declare a Vector3 (velocity) using the angle to calculate its components. I tried something like :
let velocity : Vector3<m/s> = { X = Math.Cos(angle);Y = Math.Sin(angle);Z = 0.0<m/s>} //don't compile
The code above doesn't compile because Vector3 is expecting a value in X and Y but Sin returns a float.
How can I solve this problem? If it possible I would like to perform a conversion between measure units, instead of a cast, in such a way that the compiler can guarantee that I'm doing the right thing while transforming an angle into a velocity.
Any suggestion?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这里有几个问题:
cos
需要一个无单位的值,因此您必须去掉angle
的单位;鉴于速度需要float
而不是float32
,您不妨直接转换为float
(这会删除单位)。然后,您需要重新安装这些装置。在度量单位的第一个版本中,您可以通过简单地乘以适当度量的 1 来完成此操作。现在有
LanguagePrimitives.FloatWithMeasure
,它更正确,但稍微更详细。除此之外,10 弧度是一个有趣的角度...
(请注意,
cos
和sin
是内置的)Several problems here:
cos
is expecting a unitless value, so you have to take the units offangle
; given that velocity is expectingfloat
and notfloat32
, you might as well just convert directly tofloat
(which removes the units).Then, you need to put the units back on. In first versions of units of measure, you could do this by simply multiplying by 1 in the appropriate measure. Now there is
LanguagePrimitives.FloatWithMeasure
, which is more correct, but slightly more verbose.That aside, 10 radians is a funny angle...
(Note that
cos
andsin
are built-in)好的,这是另一种方法,演示如何结合标量速度和 2d 方向来真正利用您的单位:
这给出了:
您可以通过向 Vector3 类型添加一个运算符来更进一步:
这意味着您然后可以这样做:
显然,你仍然没有真正在其中“使用”弧度,但这是预期的,无论如何弧度都是“非”单位。您可以使用它们的一种方法是如果您希望能够管理弧度和度数。您可以在 Vector3 上添加另外两个静态成员:
这看起来不错,但不幸的是它无法编译,因为一旦元组、函数和/或,方法“ofAngle”与此类型中的另一个方法具有相同的名称和签名测量单位被删除。您可以查看这个问题了解更多详情
OK, here's another take, demonstrating how you could combine a scalar speed and a 2d-direction to really make use of your units:
Which gives:
You could take it a step further by adding an operator to your Vector3 type:
Which would mean you could then do this:
Obviously, you're still not really 'using' your radians in there, but that's sort of expected, radians are sort of 'non' units anyway. One way that you could make use of them is if you wanted to be able to manage radians and degrees. You could add two other static members on your Vector3:
That looks nice, but unfortunately it won't compile because
The method 'ofAngle' has the same name and signature as another method in this type once tuples, functions and/or units of measure are erased.
You can check out this question for more details你要求的是矛盾的事情。测量单位通过使用类型推断来强制程序中的单位来帮助保证程序的正确性,因此必须显式地进行转换。
正如@Benjol 所说,您必须在有维数据和无量纲数据之间进行转换。下面的代码是一个非正式版本,我通过乘以其单位值将
float
转换为float
:请注意,您只需为 X 指定单位,其他单位是根据
Vector3
的类型声明推断的。You ask for contradictory things. Unit of Measure helps to guarantee correctness of programs by using type inference to enforce units in the programs, so conversion has to be done explicitly.
As @Benjol said, you have to convert between dimensional and dimensionless data. Below code is a informal version where I convert from
float
tofloat<m/s>
by multiplying with its unit value:Note that you only have to specify unit for X, other units are inferred based on type declaration of
Vector3
.