f#函数调用,带有参数并强制转换为度量单位

本文关键字:转换 度量 单位 函数调用 参数 | 更新日期: 2023-09-27 18:27:29

我喜欢用F#编写一些数学函数,并从C#中使用它们。由于F#使用度量单位,所以进行编译时检查真的很棒。在C#中,我已经有一个Length(转换为m、mm、km等的索引器)类,所以我想使用F#函数将其用作C#中的参数,并在那里转换为float或更具体的float。

由于我有两个参数,我很难调用函数。我想这和咖喱有关。

module Static
open Xunit
open Units.Contract // here is my Length class defined in C#
[<Measure>] type m
[<Measure>] type slabThickness = m
[<Measure>] type kN
[<Measure>] type freshConcreteDensity = kN/m^3
[<Measure>] type freshConcreteLoad = kN/m^2

let FreshConcreteLoad(slabThickness:float<m>, freshConcreteDensity:float<kN/m^3>) = slabThickness * freshConcreteDensity // 1. works
let FreshConcreteLoadL(slabThickness:Length, freshConcreteDensity:Length) = slabThickness.[Length.Units.m] *  freshConcreteDensity.[Length.Units.m] //2. works
let FreshConcreteLoadLUseMeasure(slabThickness:Length, freshConcreteDensity:Length) =  FreshConcreteLoad (slabThickness.[Length.Units.m]:float<m> freshConcreteDensity.[Length.Units.m]:float<kN/m^3>)  //3. here I struggel
// Related to 1. and works
[<Fact>]
let FreshConcreteLoad_Test() = 
    let thickness =  0.2<slabThickness>
    let density =  25.0<freshConcreteDensity> 
    let load:float<freshConcreteLoad> = FreshConcreteLoad(thickness,density)  
    Assert.Equal(load, 5.0<kN/m^2>) 
// Related to 2. and works
[<Fact>]
let FreshConcreteLoadL_Test() = 
    let thickness = new Length(0.2)
    let density = new Length(25.0) // dont care that this is now also a length, just for testing. in real live here would be a class for kN
    let load:float = FreshConcreteLoadL(thickness,density)  
    Assert.Equal(load, 5.0)
// Related to 3. and I struggle with the function call
[<Fact>]
let FreshConcreteLoadLUseMeasure_Test() = 
    let thickness = new Length(0.2)
    let density = new Length(25.0) // dont care that this is now also a length, just for testing. in real live here would be a class for kN
    let load:float = FreshConcreteLoadLUseMeasure(thickness,density)  
    Assert.Equal(load, 5.0)

f#函数调用,带有参数并强制转换为度量单位

您的3。函数定义不是有效的F#函数定义。如果需要调用另一个函数"FreshConcreteLoad()",则不能在函数调用中使用类型注释。也许您想将函数参数强制转换为度量单位,但无法执行此强制转换,因为C#中不存在F#度量单位,因此C#值无法直接强制转换。

你可以做的是创建几个转换F#函数的助手,比如:

let convToLength (inp: float) = inp * 1.0<m>
let convToDensity (inp: float) = inp * 1.0<kN/m^3>

并将第三个函数定义为:

let FreshConcreteLoadLUseMeasure(slabThickness:Length, freshConcreteDensity:Length) =  FreshConcreteLoad (convToLength slabThickness.[Length.Units.m], convToDensity freshConcreteDensity.[Length.Units.m]) 

或者直接在调用中执行转换:

let FreshConcreteLoadLUseMeasure(slabThickness:Length, freshConcreteDensity:Length) =  FreshConcreteLoad (1.0<m> * slabThickness.[Length.Units.m], 1.0<kN/m^3> * freshConcreteDensity.[Length.Units.m])