单例 DU 中的“|”是什么意思?

sdg*_*sdh 3 f#

考虑这个 DU:

type Foo = | Foo
Run Code Online (Sandbox Code Playgroud)

我的理解是,这是等价的:

type Foo = Foo
Run Code Online (Sandbox Code Playgroud)

然而,如果我们引入泛型,它们就不是:

// Does not compile
type Bar<'t> = Bar
Run Code Online (Sandbox Code Playgroud)
// Compiles
type Bar<'t> = | Bar
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?


更多发现:

// Works
type Bar<'t> = Bar of 't
Run Code Online (Sandbox Code Playgroud)
// Works
type Bar<'t> = | Bar of 't
Run Code Online (Sandbox Code Playgroud)

bri*_*rns 5

我认为这里有两个有趣的案例。第一个是:

type Foo = Foo
Run Code Online (Sandbox Code Playgroud)

乍一看,这看起来像是自引用类型别名,但这是不允许的,因此编译器将其接受为有效的 DU。这是正确的行为,尽管很微妙。

第二个有趣的案例是:

type Bar<'t> = Bar   // Error: The type 'Bar<_>' expects 1 type argument(s) but is given 0
Run Code Online (Sandbox Code Playgroud)

乍一看,这也像是一个自引用类型别名,但类型参数的数量错误。由于引用无效,编译器在有机会意识到它实际上正在查看有效的 DU 定义之前会发出错误。我认为人们可以合理地认为这是编译器中的一个错误,我建议将其作为问题提交给 F# 编译器团队。预期行为是这是一个有效的 DU,就像type Foo = Foo和 一样type Bar<'t> = | Bar

另请注意,以下行为(正确地)是不允许的:

type Foo = Foo
Run Code Online (Sandbox Code Playgroud)

编译器源代码有以下内容:

type Bar<'t> = Bar   // Error: The type 'Bar<_>' expects 1 type argument(s) but is given 0
Run Code Online (Sandbox Code Playgroud)