如何在 F# 中扩展 System.DateTime?

How can I extend System.DateTime in F#?

我想按以下方式扩展 DateTime:

[<AutoOpen>]
type System.DateTime with
  member this.floor (interval: TimeSpan) =
    this.AddTicks(-(this.Ticks % interval.Ticks))

  member this.ceiling (interval: TimeSpan) =
    let overflow = this.Ticks % interval.Ticks
    if overflow = 0 then this else this.AddTicks(interval.Ticks - overflow)

  member this.round (interval: TimeSpan) =
    let halfIntervalTicks = (interval.Ticks + 1) >>> 1
    this.AddTicks(halfIntervalTicks - ((this.Ticks + halfIntervalTicks) % interval.Ticks))

基于 aj.toulan 的 C# 答案:DateTime Round Up and Down

但这行不通;显然我应该使用一个模块,但是我如何获得 'this' 部分?正确的语法是什么?

我收到这个错误:

[FS0644] Namespaces cannot contain extension members except in the same file and namespace declaration group where the type is defined. Consider using a module to hold declarations of extension members.

根据错误消息判断,我假设您在命名空间内有该声明,如下所示:

namespace N

type System.DateTime with
    ...

如果是这样,那么我的第一个问题是:为什么首先需要名称空间?改用模块! F# 中的模块更加惯用,让您可以做更多的事情:

module N

type System.DateTime with
    ...

但是,如果您出于某种原因必须拥有命名空间,您仍然可以通过使用错误消息本身中提供给您的建议来完成这项工作:将扩展放入模块中!

namespace N

module M =    
    type System.DateTime with
        ...

当然,现在您还必须 open 使用站点的那个模块:

open N
open M  // <-- extra open

... DateTime.Now.floor ...

但是您也可以通过给该模块一个 [<AutoOpen>] 属性来避免这种情况:

namespace N

[<AutoOpen>]
module M =    
    type System.DateTime with
        ...

现在使用站点可以只打开命名空间:

open N

... DateTime.Now.floor ...

另外,请注意类型扩展中的 [<AutoOpen>] 是 non-sensical。类型扩展总是打开的,这就是它们的意义所在,您不需要显式打开它们或具有 AutoOpen 属性。