views:

113

answers:

1

(Yes, still playing with units of measure)

I've just started using units of measure for something other than float for the first time.

After starting off complicated, I discovered that you can re-use units of measure across multiple 'types'.

[<Measure>] type mm

let a = 1<mm>
let b = 1.<mm>

Now I'm sitting here wondering how to update my existing mm type to reflect this possibility:

[<Measure>]
type mm =
    static member perMetre = 1000.0<mm/m>
    static member fromMetre (v:float<m>) = v * mm.perMetre
    static member toMetre (v:float<mm>) = v / mm.perMetre
    static member lift (v:float) = v * 1.0<mm>

The question: How do I write a function that can convert from mm to m (say) that can handle int<mm> -> int<m> AND float<mm> -> float<m>?

UPDATE

Thanks to Kurt, here's the new version:

[<Measure>]
type mm =
    static member private perMetreFloat = 1000.0<mm/m>
    static member private perMetreInt = 1000<mm/m>
    [<OverloadIDAttribute("float")>]
    static member fromMetre (v:float<m>) = v * mm.perMetreFloat
    [<OverloadIDAttribute("float")>]
    static member toMetre (v:float<mm>) = v / mm.perMetreFloat
    [<OverloadIDAttribute("float")>]
    static member lift (v:float) = v * 1.0<mm>
    [<OverloadIDAttribute("int")>]
    static member fromMetre (v:int<m>) = v * mm.perMetreInt
    [<OverloadIDAttribute("int")>]
    static member toMetre (v:int<mm>) = v / mm.perMetreInt
    [<OverloadIDAttribute("int")>]
    static member lift (v:int) = v * 1<mm>
+1  A: 

Simply overloading works sometimes (if you have an argument):

[<Measure>]
type MM =
    static member perMetre = 1000.0<mm/m>
    static member fromMetre (v:float<m>) = v * MM.perMetre
    static member toMetre (v:float<mm>) = v / MM.perMetre
    [<OverloadIDAttribute("0")>]
    static member lift (v:float) = v * 1.0<mm>
    [<OverloadIDAttribute("1")>]
    static member lift (v:int) = v * 1<mm>
Kurt Schelfthout
Lurvely, works a treat, I have included the result in the bottom of my question.
Benjol