F# 跳过范围运算符

F# Skip Range Operator

我正在尝试在 F# 中生成日期(时间段)列表,我在 (F# generate a sequence/array of dates) 找到了答案并且它运行良好。

但是我无法绕过 (+) 静态成员的定义。

静态成员 (+) (d:DateTime, Span wrapper) = ...

特别是 Span 包装器部分。我什至重写为:

静态成员 (+) (d:DateTime, wrapper:Span) = ...

即使编译 (fsi) 它也不起作用。

只有当我重写它以匹配原始语法时,它才会按预期工作。

我查看了 MSDN 文档以及我拥有的一些 F# 书籍,但找不到任何内容来解释 (+) 运算符的特定语法。

对于上下文,这里是原始示例:

type Span = 
  | Span of TimeSpan
  static member (+) (d:DateTime, Span wrapper) = d + wrapper
  static member Zero = Span(new TimeSpan(0L))

(+)中,作者直接在参数上使用了模式匹配。这意味着 wrapper 的类型为 TimeSpan,而 d + wrapperDateTimeTimeSpan

之间的操作

以下详细形式的示例看起来更清晰:

static member (+) (d:DateTime, span: Span) = 
    match span with
    | Span wrapper ->
         d + wrapper

这是一个非常微妙的语法技巧,您可以将其与以下形式的类型定义一起使用:

type MyNumber = MyNumber of int

这定义了一个 type MyNumber ,它是一个使用 constructor 包装的整数,它也被命名为 MyNumber.所以,我们定义了一个类型和一个同名的构造函数。我们可以使用不同的名称:

type MyNumberType = MyNumberCtor of int

以下语法用于提取值时的模式匹配。在这里,我们使用构造函数:

let getNumber (MyNumber n) = n
let getNumber (MyNumberCtor n) = n

以下语法为类型注解(使用类型名称):

let doNothing (n:MyNumber) = 1
let getNumber (n:MyNumberType) = 1

在这里,我们不能对 n 做太多事情,因为它是包装值 - 所以我们必须使用模式匹配来提取它。正如您在@pad 的回答中看到的那样,编写模式匹配的另一种方法是使用 match 构造。无论如何,与运算符和类型没有什么特别的关系——这只是人们在定义包装器时有时会使用的一种命名技巧。