I'm trying to write a "unit of measure" converter in F#.
I have defined two units of measure, KWh
and MWh
and I am trying to write a function to convert between the two that will pattern match on the numeric type. I could have a float, decimal, int of KWh to convert to MWh.
[<Measure>]
type KWh
[<Measure>]
type MWh
// want to do this, but can't because x is not x:obj,
// its something like x:float<KWh>
let toMWh x =
match x with
| :? float<KWh> -> x * (1.0<MWh>/1000.0<KWh>)
| :? int<KWh> -> // ...
// above code not valid f#
I'm not able to figure out how to correctly branch o开发者_开发技巧n type when I don't have a obj type.
Honestly, I'd just do the low-budget overloading solution:
[<Measure>]
type KWh
[<Measure>]
type MWh
type Convert =
static member toMWh (x:float<KWh>) = x * 1.0<MWh> / 1000.0<KWh>
static member toMWh (x:int<KWh>) = x * 1<MWh> / 1000<KWh>
printfn "%d" (int(Convert.toMWh(5000<KWh>)))
printfn "%f" (float(Convert.toMWh(5500.0<KWh>)))
That said, someone may come up with a clever, type-safe way to do it with inline
(I'm not sure offhand if it's possible). I would avoid your run-time matching, since it sacrifices static type-safety (which is kinda the point of units). (Also, it is impossible to do run-time matching of units anyway, since units are erased during compilation.)
精彩评论