This question is closely related to these ones (1, 2, 3)
I\'m using an external library which doens\'t (yet) handle units of measure. I want to be able to \
For now, boxing and casting appears to work:
let MyUnitAwareClient (s:float<'u>) =
let result = s |> float |> ExternalNonUnitAwareFunction
(box result :?> float<'u>)
I wouldn't be surprised if the units of measure stuff goes through some further changes before release, though, which might break this. You can also make a more generic version, such as:
let reunit (f:float -> float) (v:float<'u>) =
let unit = box 1. :?> float<'u>
unit * (f (v/unit))
EDIT
There is now a FloatWithMeasure
function to 'cast to units':
http://msdn.microsoft.com/en-us/library/ee806527(VS.100).aspx
And just for fun, here is the opposite:
let deunit (fn:float<'u> -> float<'v>) (v:float) =
let unit = box 1. :?> float<'u>
fn(v * unit) |> float
Test :
#light
[<Measure>]type mm
let reunit (fn:float -> float) (v:float<'u>) =
let unit = box 1. :?> float<'u>
unit * (fn(v/unit))
let deunit (fn:float<'u> -> float<'v>) (v:float) =
let unit = box 1. :?> float<'u>
fn(v * unit) |> float
let nounits v = v + 2.5 //function with no units
let withunits = reunit nounits //make it handle units (run with next line)
withunits 2.5<mm> //try it -> 5.0<mm>
let newnounits = deunit withunits //remove unit handling
newnounits 2.5 //try it -> 5.0<mm>
let withunits2 = reunit newnounits //reunit to another function
withunits2 2.5<mm^2> //try with different units
Weird stuff with that #"(£$! Value restriction error in there if you run let withunits = reunit nounits
on it's own. So you have to run it with the line that uses withunits. I guess it's not surprising, you have to pass in the (v:float<'u>)
to reunit for F# to be able to work out what 'u is. Possibly makes reunit of limited interest, I guess...
UPDATE: A slightly kooky workaround is to pass in 'model' values
let reunit2 (fn:float -> float) (model:float<'u>*float<'v>) =
let unitin = box 1. :?> float<'u>
let unitout = box 1. :?> float <'v>
(fun v -> (fn(v / unitin)) * unitout)
let withunits3 = reunit2 nounits (0.<mm>, 0.<mm^2>)
withunits3 3.5<mm>