我最近开始玩F#中的计量单位,并认为我可以写一个非常简单的例子来计算增值税率和净总额的总额。
例如:
净额可能等于600.00 增值税税率为20% 哪个应该给出总金额720.00
我有以下类型
[<Measure>] type net
[<Measure>] type vatRate
[<Measure>] type vatValue = net * vatRate
[<Measure>] type gross
以下功能
let calculateVat (netValue : float<net>) (vat : float<vatRate>) = netValue * vat
let calculateGross (netValue : float<net>) (vat : float<vatValue>) = netValue + vat
通过以下测试:
let calcVatTest = calculateVat 600.00<net> 0.2<vatRate> = 120.00<vatValue>
let calcGrossTest = calculateGross 600.00<net> 120.00<vatValue> = 720.00<gross>
我遇到的问题是我无法获得calculateGross函数的正确语法,并且我收到了编译错误: “度量单位'vatValue'与度量单位'net'不匹配”
好像我需要定义类似于以下的内容:
[<Measure>] type gross = net + vatValue
但编译器不喜欢+
我有什么想法可以实现这个目标?
由于
答案 0 :(得分:1)
测量表达式仅支持运算符*
,/
和^
- 尽管-
可用于构造负指数。从逻辑上讲,这是有道理的,因为为了使用维度分析,编译器必须考虑每个因子由标量和单个单位或单位的乘积组成。
老实说,这似乎不适合衡量计量单位。看起来它只是使你的代码变得复杂而没有提供太多的表现力。
进一步阅读
答案 1 :(得分:1)
我知道你没有问过,但是这个问题太过分了,这太过于无法发表评论。我想你可能不希望计量单位为毛,等等,因为我预计毛,净等都是货币。
更像这样(假设增值税是欧洲货币的百分比):
[<Measure>] type euro
[<Measure>] type percent
let gross = 100.0<euro>
let vatRate = 5.0<percent>
我的意思是说我认为你已经掌握了使用计量单位的错误方法。总收入不是衡量标准 - 它是一个数字;同样vatRate。
答案 2 :(得分:0)
在您的示例中,问题在于您尝试添加两个具有不同单位的内容(价格不含增值税和增值税值) - 静态类型不允许 - 您只能添加相同单位的内容(即计量单位背后的部分原则 - 你无能为力。)
我认为最自然的解决方案(然而,这并不能给您提供强有力的安全保障)是增值税率无量纲数。
一般情况下(考虑物理意义时),费率是没有单位的数字的示例 - 对于某些数字X<unit> / Y<unit>
和X
,费率通常计算为Y
同一unit
,因此该部门在分割期间取消。
所以你可以这样写:
[<Measure>] type net
[<Measure>] type vatRate = 1
[<Measure>] type vatValue = net * vatRate
let calculateVat (netValue : float<net>) (vat : float<vatRate>) = netValue * vat
let calculateGross (netValue : float<net>) (vat : float<vatValue>) = netValue + vat
这意味着float<vatRate>
实际上只是普通float
而vatValue
与net
相同(但您仍然可以在代码中使用别名作为文档)。
因此,这消除了增值税价格与不含增值税的价格之间的区别,但至少您的程序仍然静态地区分代表货币的浮动和代表数字的浮动。