F#Ununit - 聚集在函数内部(F# Ununit - reunit inside a fu

2019-07-17 11:56发布

这个问题是密切相关的这些的( 1 , 2 , 3 )

我使用它好好尝试一下(还)处理度量单位的外部库。 我希望能够“ununit”值之前,我通过他们,然后“reunit”他们当我得到的结果返回。

美中不足的是,我想,以避免被迫提前申报哪个单位。

示例代码段

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#的最终版本将包括功能做到这一点。

Answer 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



Answer 2:

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

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>)以reunit为F#是能制定出什么” U可能是使有限的兴趣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>


文章来源: F# Ununit - reunit inside a function