简体   繁体   English

带参数的f#函数调用并转换为度量单位

[英]f# function call with parameters and cast to units of measure

I like to write some math functions in F# and use them from C#. 我喜欢用F#编写一些数学函数并从C#中使用它们。 As F# uses units of measures it is really great to have the compile time check. 由于F#使用度量单位,因此进行编译时间检查确实很棒。 In C# I already have a Length (indexer that converts to m, mm, km etc) class so I want to use that as a parameter from C# using the F# function and convert it there to float or more specific float. 在C#中,我已经有了一个Length(可将其转换为m,mm,km等的索引器)类,因此我想使用F#函数将其用作C#中的参数并将其转换为float或更特定的float。

As I have two parameters I struggle calling the functions. 因为我有两个参数,所以我很难调用这些函数。 I guess it has something to do with currying. 我想这与欺骗有关。

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)

Your 3. function definition is not a valid F# function definition. 您的3.函数定义不是有效的F#函数定义。 If you need to call another function 'FreshConcreteLoad()' you cannot use type annotations in function call. 如果需要调用另一个函数“ FreshConcreteLoad()”,则不能在函数调用中使用类型注释。 Maybe you wanted to cast function parameters to units of measure but this cast cannot be performed because F# units of measure are not exist in C# so C# value cannot be directly casted to it. 也许您想将函数参数转换为度量单位,但由于C#中不存在F#度量单位,因此无法执行此转换,因此无法将C#值直接转换为它。

What you could do is to create a couple of helper converting F# functions like: 您可以做的是创建几个帮助程序来转换F#函数,例如:

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

and define 3rd function as: 并将第三个函数定义为:

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

or perform conversion directly in the call: 或直接在通话中执行转换:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM