簡體   English   中英

F#計量單位,在不丟失測量類型的情況下進行鑄造

[英]F# Unit of Measure, Casting without losing the measure type

是否有內置版本的類型轉換功能可以保留單位,如果沒有,我將如何制作它們? 因此,例如使用此代碼,如何將intWithSecondsMeasure轉換為float而不會丟失度量或乘以1.0<s>

[<Measure>] type s
let intWithSecondsMeasure = 1<s>
let justAFloat = float intWithSecondsMeasure 

@kvb提供的答案肯定有效,但我不想使用unbox運算符進行此轉換。 有一個更好的,內置的方式,我認為應編譯為IL的NOP(我沒有檢查,但unbox可能最終將作為IL中的unbox指令,因此添加運行時類型檢查)。

在F#中進行單位轉換的首選方法是LanguagePrimitives.TypeWithMeasureMSDN )。

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

我編譯了kvb和Johannes答案的代碼。

約翰內斯回答

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/float_unit@4::.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

看看我對這個問題的回答:

單位安全的平方根

這表明今天:

[<Measure>] 
type s
let intWithSecondsMeasure = 1<s>

let intUtoFloatU< [<Measure>] 'u>( x : int<'u> ) : float<'u> = //'
    let i = int x       //  drop the units
    let f = float i     //  cast
    box f :?> float<'u> //' restore the units

let floatWithS = intUtoFloatU intWithSecondsMeasure

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM