是否存在保留单位的类型铸造函数的版本,如果不是,我将如何制作它们?因此,举例来说,通过这段代码,我如何将intWithSecondsMeasure投射到一个浮点数而不会丢失度量或乘以1.0<s>
?F#计量单位,铸造时不会丢失度量类型
[<Measure>] type s
let intWithSecondsMeasure = 1<s>
let justAFloat = float intWithSecondsMeasure
是否存在保留单位的类型铸造函数的版本,如果不是,我将如何制作它们?因此,举例来说,通过这段代码,我如何将intWithSecondsMeasure投射到一个浮点数而不会丢失度量或乘以1.0<s>
?F#计量单位,铸造时不会丢失度量类型
[<Measure>] type s
let intWithSecondsMeasure = 1<s>
let justAFloat = float intWithSecondsMeasure
由@kvb提供的答案肯定有效,但我不希望在此转换中使用unbox
运算符。有一种更好的方式,我认为应该被编译为IL的NOP(我没有检查过,但unbox可能最终将作为IL中的unbox
指令并因此增加了运行时类型检查)。
在F#中执行单位转换的首选方式是LanguagePrimitives.TypeWithMeasure
(MSDN)。
let inline float32toFloat (x:float32<'u>) : float<'u> =
x |> float |> LanguagePrimitives.FloatWithMeasure
我不认为有一个内置的方式做到这一点,但你可以很容易地定义自己的单位保留转换功能:
let float_unit (x:int<'u>) : float<'u> = unbox float x
let floatWithSecondsMeasure = float_unit intWithSecondsMeasure
威尔的东西与此签名库中去?显然,它可以根据计划的FloatWithMeasure进行写入,但有一个明确的单元安全直接可用的函数会更好。 – 2009-12-13 17:10:01
这个答案现在给出警告。 “这种类型的测试或向下会忽略度量单位''''我加了IL。” – gradbot 2014-02-15 18:46:53
我编译了代码从kvb和约翰内斯答案。
约翰内斯回答与加括号
let float32toFloat (x:int<'u>) : float<'u> =
x |> float |> LanguagePrimitives.FloatWithMeasure
.method public static float64 float32toFloat(int32 x) cil managed
{
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldarg.0
IL_0001: conv.r8
IL_0002: ret
} // end of method Program::float32toFloat
KVB答案。
let float_unit (x:int<'u>) : float<'u> = unbox (float x)
.method public static float64 float_unit(int32 x) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.0
IL_0001: conv.r8
IL_0002: box [mscorlib]System.Double
IL_0007: unbox.any [mscorlib]System.Double
IL_000c: ret
} // end of method Program::float_unit
KVB答案
let float_unit (x:int<'u>) : float<'u> = unbox float x
.method public static float64 float_unit(int32 x) cil managed
{
// Code size 19 (0x13)
.maxstack 8
IL_0000: newobj instance void Program/[email protected]::.ctor()
IL_0005: call !!0 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::UnboxGeneric<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,float64>>(object)
IL_000a: ldarg.0
IL_000b: tail.
IL_000d: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,float64>::Invoke(!0)
IL_0012: ret
} // end of method Program::float_unit
我加了IL。从int转换为float以与问题保持一致。 http://stackoverflow.com/a/21802111/17919 – gradbot 2014-02-15 19:01:53