考虑这个 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)
我认为这里有两个有趣的案例。第一个是:
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)