跨类型转换维护计量单位

发布于 2025-01-08 10:29:35 字数 811 浏览 0 评论 0原文

如果我们定义一个度量单位,例如:

[<Measure>] type s

然后是一个带有度量的整数

let t = 1<s>

,然后将其转换为浮点数,

let r = float t

我们会看到没有度量类型的r = 1.0。这看起来很奇怪,因为所有测量信息都丢失了。

您可以使用 LanguagePrimitives.FloatWithMeasure 来转换回浮点数,例如

let inline floatMeasure (arg:int<'t>) : (float<'t>) =
    LanguagePrimitives.FloatWithMeasure (float arg)

强制使用正确的类型,但这感觉不像测量单位的文档那样是正确的解决方案(http:// msdn.microsoft.com/en-us/library/dd233243.aspx)说

但是,为了编写互操作性层,还可以使用一些显式函数将无单位值转换为有单位值。这些位于 Microsoft.FSharp.Core.LanguagePrimitives 模块中。例如,要将无单位浮点数转换为浮点数,请使用 FloatWithMeasure,如以下代码所示。

这似乎表明在 F# 代码中应避免使用该函数。

有没有更惯用的方法来做到这一点?

If we define a unit of measure like:

[<Measure>] type s

and then an integer with a measure

let t = 1<s>

and then convert it to a float

let r = float t

we see that r = 1.0 without a measure type. This seems very odd, as all the measure information has been lost.

You can use LanguagePrimitives.FloatWithMeasure to convert back to a float with something like

let inline floatMeasure (arg:int<'t>) : (float<'t>) =
    LanguagePrimitives.FloatWithMeasure (float arg)

which enforces the right types, but this doesn't feel like the right solution as the docs for units of measure (http://msdn.microsoft.com/en-us/library/dd233243.aspx) say

However, for writing interoperability layers, there are also some explicit functions that you can use to convert unitless values to values with units. These are in the Microsoft.FSharp.Core.LanguagePrimitives module. For example, to convert from a unitless float to a float, use FloatWithMeasure, as shown in the following code.

Which seems to suggest that the function should be avoided in F# code.

Is there a more idiomatic way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

表情可笑 2025-01-15 10:29:35

这是工作片段,它完全满足您的需要,但会发出警告

stdin(9,48):警告 FS0042:此构造已弃用:它仅适用于 F# 库)):

[<NoDynamicInvocation>]
let inline convert (t: int<'u>) : float<'u> = (# "" t : 'U #)

[<Measure>] type s
let t = 1<s>
let t1 = convert t // t1: float<s>

但是,我不建议使用这种方法。
首先,UoM 是编译时的,而类型转换let r = float t 是运行时的。在调用时,int ->; float 不知道它是 int 还是 int。因此它根本无法在运行时推断出正确的float<'u>

另一种想法是,曼彻斯特大学背后的哲学比它所描述的更广泛。这就像对编译器说:“好吧,它是 int,但请将其视为 int”。目标是避免偶尔的不当使用(例如,将 int 添加到 int)。
有时,int -> 没有任何意义。 float转换:想想int,没有float的意义。

进一步阅读,感谢 @kvb 指出本文。

Here's working snippet that does exactly what you need although gives warning

stdin(9,48): warning FS0042: This construct is deprecated: it is only for use in the F# library)):

[<NoDynamicInvocation>]
let inline convert (t: int<'u>) : float<'u> = (# "" t : 'U #)

[<Measure>] type s
let t = 1<s>
let t1 = convert t // t1: float<s>

However, I wouldn't suggest this approach.
First of all, UoM are compile-time, while type conversion let r = float t is runtime. At the moment of invocation, int -> float has no idea of whether it is int<s> or int<something_else>. So it is simply unable to infer a proper float<'u> at runtime.

Another thought is that philosophy behind UoM is wider than it's described. It is like saying the compiler, "well, it is int, but please treat it as int<s>". The goal is avoiding occasional improper use (e.g., adding int<s> to int<hours>).
Sometimes it makes no sense of int -> float conversion: think of int<ticks>, there is no sense of float<ticks>.

Further reading, credits to @kvb for pointing on this article.

甜警司 2025-01-15 10:29:35

(警告:我在愤怒中没有太多使用单位。)

我认为使用例如FloatWithMeasure的唯一负面影响是单位转换方面(从无单位到有单位)。我认为这在概念上与数字表示转换方面正交(例如 intfloat)。然而(我认为)没有库函数可以对单位值进行数字表示转换。也许这反映了这样一个事实,即大多数单位值都会模拟现实世界的连续值,因此通常不使用像 int 这样的离散表示形式(例如 1感觉不对;你肯定是指 1.0)。

因此,我认为“转换表示”然后“重新调整单位”很好,但我想知道首先如何获得具有不同表示的值,因为这些表示对于域来说通常是固定的(例如使用 <代码>浮动无处不在)。

(无论如何,我确实喜欢您的 floatMeasure 函数,它消除了单位方面与表示方面的混淆,因此,如果您确实只需要更改表示,您就有办法表达直接就可以了。)

(Caveat: I've not used units much in anger.)

I think that the only negative for using e.g. FloatWithMeasure is the unit-casting aspect (unitless to unitful). I think this is conceptually orthogonal to the numeric-representation-casting aspect (e.g. int to float). However there is (I think) no library function to do numeric-representation-casting on unit-ful values. Perhaps this is reflective of the fact that most unitful values model real-world continuous values, as so discrete representations like int are typically not used for them (e.g. 1<s> feels wrong; surely you mean 1.0<s>).

So I think it's fine to 'cast representations' and then 'readjust units', but I wonder how you got the values with different representations in the first place, as it's often typical for those representations to be fixed for a domain (e.g. use float everywhere).

(In any case, I do like your floatMeasure function, which un-confounds the unit-aspect from the representation-aspect, so that if you do need to only change representation, you have a way to express it directly.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文