2009-12-12 11 views
13

Gibt es eingebaute Version des Typs Casting-Funktionen, die Einheiten erhält und wenn nicht, wie würde ich sie machen? Also zum Beispiel mit diesem Code, wie würde ich intWithSecondsMeasure in eine Float-Funktion umwandeln, ohne das Maß zu verlieren oder mit 1.0<s> zu multiplizieren?F # Maßeinheit, Gießen, ohne den Maßtyp zu verlieren

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

Antwort

11

Die Antwort von @ kvb funktioniert sicherlich, aber ich würde lieber den Operator unbox für diese Konvertierung verwenden. Es gibt einen besseren, eingebauten Weg, den ich denke, sollte als NOP zu IL kompiliert werden (ich habe nicht überprüft, aber Unbox wird wahrscheinlich als unbox Anweisung in IL enden und fügt somit eine Laufzeittypüberprüfung hinzu).

Die bevorzugte Methode zur Konvertierung von Einheiten in F # ist LanguagePrimitives.TypeWithMeasure (MSDN).

let inline float32toFloat (x:float32<'u>) : float<'u> = 
    x |> float |> LanguagePrimitives.FloatWithMeasure 
+0

Ich habe die IL hinzugefügt. Wirf von int in float, um mit der Frage konsistent zu sein. http://stackoverflow.com/a/21802111/17919 – gradbot

8

Ich glaube nicht, dass es eine eingebaute Möglichkeit, es zu tun, aber Sie können Ihre eigene Einheit erhaltKonvertierungsFunktion leicht definieren:

let float_unit (x:int<'u>) : float<'u> = unbox float x 
let floatWithSecondsMeasure = float_unit intWithSecondsMeasure 
3

Siehe meine Antwort auf diese Frage:

Unit-safe square roots

was darauf hindeutet, das heute:

[<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 
+0

Will etwas mit dieser Signatur in der Bibliothek gehen? Offensichtlich ist es in Bezug auf das geplante FloatWithMeasure schreibbar, aber es wäre schöner, eine Funktion zu haben, die eindeutig direkt von der Einheit abhängig ist. –

+0

Diese Antwort gibt jetzt eine Warnung aus. "Diese Art Test oder Downcast ignoriert die Maßeinheit '' – gradbot

4

Ich kompilierte den Code von kvb und Johannes antwortet.

Johannes antworten

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 Antwort mit zusätzlichen Klammern.

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 Antwort

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 
Verwandte Themen