内部类型上的F#运算符重载是否可用于程序集中的所有文件?

时间:2018-09-26 09:43:09

标签: f#

我有一些强制使用数值范围的类型,并且我在单个项目的许多文件中使用它们。他们看起来像这样:

[<Struct>]
type NonNegativeMoney =
    new(x) =
        if x < 0m then invalidArg "x" "Ruh-roh..."
        { Value = x }
    val Value : decimal
    static member (+) (x: NonNegativeMoney, y: NonNegativeMoney) = NonNegativeMoney(x.Value + y.Value)

我现在想使这些类型成为程序集的内部类型,并且仅将我的OO类型模型保留为公共状态。但是,当我将这些类型翻转为内部类型时,出现以下编译器错误:

  

成员或对象构造函数“ op_Addition”不是公共的。私人的   成员只能在声明类型内访问。受保护的   成员只能从扩展类型访问,而不能是   从内部Lambda表达式访问。

问题Why does the F# compiler fail with this infix operator?中已解决了此问题的原因。答案中提出的解决方案是使用F# signature files将类型设置为内部类型。这适用于该问题中OP的场景,在该场景中,运算符的使用仅限于同一文件中的类型。但是,我似乎找不到一种使它起作用的方法,因此可以从项目中的所有文件访问该操作符。如果我使用签名文件,则它在文件内起作用,但在文件间不起作用。

有什么办法可以使该类型在程序集内部,但是在我项目中的所有文件中可见吗?我想保留运算符,因为我正在使用像Seq.sum这样的库函数,这些函数需要它们的求和类型。

1 个答案:

答案 0 :(得分:0)

您可以在模块而不是类型中定义重载:

[<Struct>]
type internal NonNegativeMoney =
    new(x) =
        if x < 0m then invalidArg "x" "Ruh-roh..."
        { Value = x }
    val Value : decimal

let internal (+) (x: NonNegativeMoney) (y: NonNegativeMoney) = NonNegativeMoney(x.Value + y.Value)

...但是这将覆盖常规(+)运算符,这可能就是您排除它的原因。使用自定义运算符(例如++)可能是一个合理的折衷方案。

可以通过标记模块[<AutoOpen>]使操作员可用于整个项目。