3

这个问题与这些问题密切相关(1 , 2 , 3

我正在使用一个(尚未)处理度量单位的外部库。我希望能够在传递它们之前将它们“ununit”,然后在我得到结果时“reunit”它们。

问题是我想避免被迫提前宣布 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

我还没想好怎么处理这个...

更新 如果我理解正确,F# 的最终版本将包含执行此操作的函数。

4

2 回答 2

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

于 2009-09-10T17:37:23.493 回答
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自己运行它,就会出现价值限制错误。所以你必须使用使用 withunits 的行来运行它。我想这并不奇怪,你必须传入(v:float<'u>)to reunit for F# 能够弄清楚'u 是什么。我猜可能会使重聚的兴趣有限...

更新:一个有点古怪的解决方法是传递“模型”值

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>
于 2009-09-23T13:28:38.357 回答