如果我们定义一个度量单位,如:
[<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#代码中应避免使用该函数。
是否有更惯用的方式来做到这一点?
答案 0 :(得分:1)
(警告:我没有在愤怒中使用单位。)
我认为使用例如FloatWithMeasure
是单位投射方面(无统一的单位)。我认为这在概念上与数字表示 - 投射方面正交(例如int
到float
)。但是(我认为)没有库函数来对单位值进行数值表示式转换。也许这反映了这样一个事实:大多数单元值模拟真实世界的连续值,因为像int
这样的离散表示通常不会用于它们(例如1<s>
感觉错误;当然你的意思是{{1 }})。
所以我认为'表示'然后'重新调整单位'是好的,但是我想知道你是如何得到具有不同表示的值的,因为通常这些表示被修复为域(例如,到处使用1.0<s>
。
(在任何情况下,我都喜欢你的float
函数,它从表示方面解除单位方面的混淆,所以如果你只需要改变表示,你就有办法表达直接。)
答案 1 :(得分:1)
这里的工作代码段完全符合您的要求,但会发出警告
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<s>
还是int<something_else>
。因此,它无法在运行时推断出正确的float<'u>
。
另一个想法是,UoM背后的哲学比它描述的更广泛。这就像说编译器,&#34;它是int
,但请将其视为int<s>
&#34;。目标是避免偶尔使用不当(例如,将int<s>
添加到int<hours>
)
有时候int -> float
转换毫无意义:想到int<ticks>
,就没有float<ticks>
的感觉。
Further reading,指向@kvb指的是这篇文章。