2009-09-09 40 views
3

这个问题是密切相关的这些的(123F#Ununit - reunit功能

我用它好好尝试一下(还)的外部库处理措施的单位内。我希望能够在我把它们传入之前将'ununit'的值,然后在重新获得结果时'重新组合'它们。

问题是我想避免被迫提前宣布WHICH单位。

范例片段

let ExternalNonUnitAwareFunction s = s + 1. 

let MyUnitAwareClient (s:float<'u>) = //' 
    //1. this option "flattens" to no unit, or fixes to first inferred unit 
    //let (unit:float<'u>) = 1.0<_> 
    //2. this works fine, except for 0! 
    let unit = s/(float s) 
    s |> float |> ExternalNonUnitAwareFunction |> (*) unit 

我没有设法制定出如何处理这一个...

更新 如果我有understood correctly,F#的最终版本将包括功能去做这个。

+0

月份CTP版/ 2010 Beta 1的版本有计量单位支持已签名的整型类型 - 请参阅http://blogs.msdn.com/dsyme/archive/2009/05/20/detailed-release-notes-for-the-f-may-2009-ctp-update-and- visual-studio-2010-beta1-releases.aspx – 2009-09-09 10:01:02

回答

1

现在,拳击和铸造似乎工作:

let MyUnitAwareClient (s:float<'u>) = 
    let result = s |> float |> ExternalNonUnitAwareFunction 
    (box result :?> float<'u>) 

我不会感到惊讶,如果测量的东西部经过发布前一些进一步的变化,不过,这可能会打破这一点。您也可以更宽泛的版本,如:

let reunit (f:float -> float) (v:float<'u>) = 
    let unit = box 1. :?> float<'u> 
    unit * (f (v/unit)) 

编辑

现在有一个FloatWithMeasure功能“转换为单位”:

http://msdn.microsoft.com/en-us/library/ee806527(VS.100).aspx

+0

非常好,非常感谢!我非常喜欢第二种选择,但我认为我会称之为单元化(就像memoize)。 – Benjol 2009-09-11 05:53:28

0

而只是为了好玩,这里是相反的:

let deunit (fn:float<'u> -> float<'v>) (v:float) = 
    let unit = box 1. :?> float<'u> 
    fn(v * unit) |> float 

测试:

#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 

奇怪的东西与#“(£$!如果您自行运行let withunits = reunit nounits,则会出现值限制错误。所以你必须使用与单位一起使用的线来运行它。我想这并不奇怪,你必须通过(v:float<'u>)才能使F#能够解决你的问题。可能使有限的兴趣reunit,我猜...

更新:稍微古怪的解决方法是通过在“模式”值

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>