1

我最近开始在 F# 中使用 Units Of Measure,并认为我可以编写一个非常简单的示例来计算给定增值税率和净总额的总金额。

例如:

净额可能等于 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

但是编译器不喜欢 +

任何想法我可以如何实现这一目标?

谢谢

4

3 回答 3

1

度量表达式中仅支持运算符*/和——尽管可用于构造负指数。从逻辑上讲,这是有道理的,因为为了使用维度分析,编译器必须考虑每个因素都由标量和单个单位或单位的乘积组成。^-

老实说,这似乎不是度量单位的好用处。看起来它只是使您的代码复杂化而没有提供更多的表现力。

进一步阅读

于 2013-11-02T18:00:16.413 回答
1

我知道你没有问,但这是一个太大的问题,不能忽略,也不能发表评论。我认为您可能不希望总、增值税等的计量单位,因为我希望总、净等以货币形式表示。

更像这样的东西(假设增值税是欧洲货币的百分比):

[<Measure>] type euro

[<Measure>] type percent

let gross = 100.0<euro>
let vatRate = 5.0<percent>

我的意思是说我认为你掌握了使用计量单位的错误方法。毛不是计量单位——它是一个数字;同样增值税。

于 2013-11-04T13:40:48.433 回答
0

在您的示例中,问题是您试图添加两个具有不同单位的东西(不含增值税和增值税值的价格) - 这是静态类型所不允许的 - 您只能添加相同单位的东西(这是计量单位背后的原则——对此你无能为力)。

我认为最自然的解决方案(但是,不会给您提供强有力的安全保证)是使增值税率无量纲数。

通常(在考虑物理含义时),比率是没有单位的数字的示例-比率通常是X<unit> / Y<unit>针对某些相同的数字计算的X,因此在除法期间单位会抵消。Yunit

所以你可以这样写:

[<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(但您仍然可以在代码中使用别名作为文档)。

因此,这消除了含增值税的价格和不含增值税的价格之间的区别,但至少您的程序仍然静态地区分代表货币的浮点数和仅代表数字的浮点数。

于 2013-11-02T18:03:37.970 回答