我创建了两个度量单位,美元和欧元 . 我想在运行时区分它们,所以我定义了以下区分联合 . 然后,我想像这样定义map函数:
[<Measure>] type USD
[<Measure>] type EUR
type CurrencyKind =
| CurrencyUsd of decimal<USD>
| CurrencyEur of decimal<EUR>
member this.Map<[<Measure>] 'currency> (f : decimal<'currency> -> decimal<'currency>) =
match this with
| CurrencyUsd x -> f x
| CurrencyEur x -> f x
但是,当我这样做时,我在 'currency
下收到以下错误:
FS0660 F#此代码的通用性低于其注释所需的代码,因为显式类型变量无法进行泛化 . 它被限制为“美元” .
CurrencyEur x -> f x
的 x
:
FS0001 F#计量单位'USD'与计量单位'EUR'不符
有没有什么好方法可以构建这个版本?
1 回答
定义泛型函数的方式,
map
函数的调用者定义了单位是什么,但这不正确 - 您希望map
函数本身根据值定义单位 . 这可以使用接口完成,但它变得很丑陋 .在这种情况下,我认为你可以通过定义一个新的单元类型来解决这个问题,比如
Money
:您作为参数传递给
map
的函数需要一些金额并返还一些其他金额,因此您可以给它一个decimal<Money> -> decimal<Money>
类型 . 无论是美元还是欧元,这都是map
函数可以决定的 . 在实现中,我们只需在调用f
之前将USD或EUR转换为Money,然后转换回:这可能会为您提供所需的安全性 . 如果我们计算
m + m
,那可行,因为单位仍然是钱,但如果你计算m * m
,你会得到一个编译时错误:对于记录,使用接口的丑陋版本将如下所示: