组合泛型和非泛型时,类型变量会逃逸范围 class

Type variable escapes scope when combining generic and non-generic class

我在 F# 中有一个带有单一类型参数的泛型 class,我想创建一个包含工厂方法的静态 class。当我编写 classes 时,F# 编译器生成与 "type variable escaping its scope" 相关的错误。我的问题是为什么会出现错误以及如何解决它。

我创建了一个最小尺寸的片段来演示该问题:

type Foo<'a>(element : 'a) =

    member this.Copy () = Bar.Create(element)

and Bar =

    static member Create(element : 'a) = new Foo<'a>(element)

类型中的相互递归是因为我希望类型Foo<'a>能够调用静态class中的工厂方法。上面的代码片段没有编译,错误是: "Type inference caused the type variable a to escape its scope. Consider adding an explicit type parameter declaration or adjusting your code to be less generic." 错误被注册为位于 Bar class 的 Create 方法中。不幸的是,我真的不明白这个问题,也不明白如何解决它。有什么想法吗?

这是一个额外的观察。片段

type Foo<'a>(element : 'a) =

    member this.Element = element

and Bar =

    static member Create(element : 'a) = new Foo<'a>(element)

编译。因此,该问题似乎与基于 Foo<'a> class 的 Copy() 方法进行的类型推断有关。此外,片段

type Foo<'a>(element : 'a) =

    member this.Copy () = Bar.Create(element)

and Bar =

    static member Create<'a>(element) = new Foo<'a>(element)

是一个更像 C# 的代码版本(其中静态方法显式化为泛型),也无法编译,错误为 "This code is not sufficiently generic. The type variable 'a could not be generalized because it would escape its scope."

我实际上看到了一个不同的错误,关于类型变量 'a 未解决,我可以通过使用 'a:

参数化 Bar 来绕过它
type Foo<'a>(element : 'a) =
    member this.Copy () = Bar.Create(element)

and Bar<'a> =
    static member Create(element : 'a) = new Foo<'a>(element)

恐怕我没有很好的解释为什么在你有相互递归类型的情况下需要这样做,而不是在你有单独的 Bar 类型的情况下。

我倾向于避免相互递归类型 - 离不开它们的情况很少见。大多数时候,您可以重构代码以避免递归,并且通常会得到更易于阅读和重构的代码(如有必要)。

这似乎没有使 Bar 通用:

type Foo<'a>(element : 'a) =
    member this.Copy () = Bar.Create element
and Bar =
    static member Create<'a>(element : 'a) : Foo<'a> = Foo(element)

Online Demo

不知道为什么,只是通过反复试验发现的。

递归成员的类型推断通常至少需要对某些定义进行类型注释。但是,有时您可以通过 re-ordering 定义来避免这种情况,至少在您的简化重现中可以:

type Bar = 
    static member Create(element) = Foo(element)
and Foo<'a>(element:'a) =
    member this.Copy() = Bar.Create(element)

(请注意,我什至在 Bar.Create 中删除了 element 上的注释)。

不幸的是,我不知道 easy-to-understand 对在任何特定情况下究竟需要哪些注释的解释。