我在F#中有一个带有单个类型参数的泛型类,并且想要创建一个包含工厂方法的静态类.当我编写类时,F#编译器会生成与"转换其范围的类型变量"相关的错误.我的问题是为什么错误存在以及如何解决它.
我创建了一个最小尺寸代码段来演示此问题:
type Foo<'a>(element : 'a) = member this.Copy () = Bar.Create(element) and Bar = static member Create(element : 'a) = new Foo<'a>(element)
类型中的相互递归是因为我希望类型Foo<'a>
能够在静态类中调用工厂方法.上面的代码片段没有编译,错误是:"类型推断导致类型变量a逃避其范围.考虑添加显式类型参数声明或调整代码以减少通用." 错误被注册为位于类的Create
方法中Bar
.不幸的是,我并不是真的了解这个问题,也不知道如何解决它.有任何想法吗?
这是另外一个观察.片段
type Foo<'a>(element : 'a) = member this.Element = element and Bar = static member Create(element : 'a) = new Foo<'a>(element)
编译.所以问题似乎与基于类Copy()
方法的类型推断有关Foo<'a>
.此外,该片段
type Foo<'a>(element : 'a) = member this.Copy () = Bar.Create(element) and Bar = static member Create<'a>(element) = new Foo<'a>(element)
是一个更像C#的代码版本(其中静态方法明确地是通用的),它也没有编译,错误"这段代码不够通用.类型变量'a不能一概而论,因为它会逃避其范围."
递归成员的类型推断通常需要至少对某些定义进行类型注释.但是,有时您可以通过重新排序定义来避免这种情况,至少可以在简化的复制中使用:
type Bar = static member Create(element) = Foo(element) and Foo<'a>(element:'a) = member this.Copy() = Bar.Create(element)
(请注意,我甚至取消了对注释element
中Bar.Create
).
不幸的是,我不知道在任何特定情况下都会有一个易于理解的解释.