创建辅助非泛型构造函数时 F# 中的编译器错误
Compiler error in F# when creating a secondary, non-generic constructor
我有一个泛型 class,其默认构造函数接受泛型类型的参数。创建第二个非泛型构造函数时,F# 编译器抱怨 This type parameter has been used in a way that constrains it to always be 'EmptyType'
,我根本不理解这个错误。为什么要约束?第二个构造函数与第一个构造函数的泛型 属性 有什么关系?
此示例显示错误(可在 F# playground 中重现)。请注意,只需注释第二个构造函数(第 9 行)即可解决编译问题:
type MyInterface = interface end
type EmptyType() = interface MyInterface
type RealType(v: int) =
member this.Value = v
interface MyInterface
type MyType<'T when 'T :> MyInterface>(element: 'T) =
new() = MyType(EmptyType())
member this.X = 0
[<EntryPoint>]
let main _ =
//let a = MyType() //empty constructor, 'T is EmptyType
let b = MyType(RealType(0)) //doesnt work because compiler says 'T is always EmptyType? what?
0
不确定导致 T
在这种情况下受到限制的重载构造函数的具体限制是什么,但是以下使用 static member
的代码却按预期工作:
type MyInterface = interface end
type EmptyType() = interface MyInterface
type RealType(v: int) =
member this.Value = v
interface MyInterface
type MyType<'T when 'T :> MyInterface>(element: 'T) =
static member Empty() = MyType(EmptyType())
member this.X = 0
[<EntryPoint>]
let main _ =
let a = MyType<_>.Empty()
let b = MyType(RealType(0))
0
构造函数不能是通用的。您的类型是通用的,但每个构造函数必须 return 定义它的确切类型。您不能有一个构造函数 return MyType<'t>
和另一个 return MyType<EmptyType>
。如果在 MyType<'t>
上定义构造函数,则它必须 return MyType<'t>
而不能 return MyType<EmptyType>
当编译器看到其中一个构造函数 always returns MyType<EmptyType>
时,它断定类型参数 't
必须 总是等于EmptyType
。正是在这个意义上,参数 't
被限制为 EmptyType
,如错误消息所述。
没有办法让构造函数 return 的类型与其定义的类型不同。如果您必须专门构造 MyType<EmptyType>
的实例,则可以改用静态方法:
type MyType<'t>(t: 't) =
static member CreateEmpty () = MyType(EmptyType())
但是,请注意,要调用此类方法,您仍然需要为 MyType
提供一些类型参数,例如:
let x = MyType<RealType>.CreateEmpty()
或者您可以使用通配符:
let x = MyType<_>.CreateEmpty()
在没有基础来推断通配符应该是什么的情况下,编译器将回退到 obj
(或最近的约束),因此上述调用将等同于 MyType<obj>.CreateEmpty()
。还是别扭。
为避免这种情况,更好的方法是使用同名模块:
module MyType =
let createEmpty() = MyType(EmptyType)
let x = MyType.createEmpty()
此模式广泛用于泛型类型。例如,参见 Option
或 List
。
我有一个泛型 class,其默认构造函数接受泛型类型的参数。创建第二个非泛型构造函数时,F# 编译器抱怨 This type parameter has been used in a way that constrains it to always be 'EmptyType'
,我根本不理解这个错误。为什么要约束?第二个构造函数与第一个构造函数的泛型 属性 有什么关系?
此示例显示错误(可在 F# playground 中重现)。请注意,只需注释第二个构造函数(第 9 行)即可解决编译问题:
type MyInterface = interface end
type EmptyType() = interface MyInterface
type RealType(v: int) =
member this.Value = v
interface MyInterface
type MyType<'T when 'T :> MyInterface>(element: 'T) =
new() = MyType(EmptyType())
member this.X = 0
[<EntryPoint>]
let main _ =
//let a = MyType() //empty constructor, 'T is EmptyType
let b = MyType(RealType(0)) //doesnt work because compiler says 'T is always EmptyType? what?
0
不确定导致 T
在这种情况下受到限制的重载构造函数的具体限制是什么,但是以下使用 static member
的代码却按预期工作:
type MyInterface = interface end
type EmptyType() = interface MyInterface
type RealType(v: int) =
member this.Value = v
interface MyInterface
type MyType<'T when 'T :> MyInterface>(element: 'T) =
static member Empty() = MyType(EmptyType())
member this.X = 0
[<EntryPoint>]
let main _ =
let a = MyType<_>.Empty()
let b = MyType(RealType(0))
0
构造函数不能是通用的。您的类型是通用的,但每个构造函数必须 return 定义它的确切类型。您不能有一个构造函数 return MyType<'t>
和另一个 return MyType<EmptyType>
。如果在 MyType<'t>
上定义构造函数,则它必须 return MyType<'t>
而不能 return MyType<EmptyType>
当编译器看到其中一个构造函数 always returns MyType<EmptyType>
时,它断定类型参数 't
必须 总是等于EmptyType
。正是在这个意义上,参数 't
被限制为 EmptyType
,如错误消息所述。
没有办法让构造函数 return 的类型与其定义的类型不同。如果您必须专门构造 MyType<EmptyType>
的实例,则可以改用静态方法:
type MyType<'t>(t: 't) =
static member CreateEmpty () = MyType(EmptyType())
但是,请注意,要调用此类方法,您仍然需要为 MyType
提供一些类型参数,例如:
let x = MyType<RealType>.CreateEmpty()
或者您可以使用通配符:
let x = MyType<_>.CreateEmpty()
在没有基础来推断通配符应该是什么的情况下,编译器将回退到 obj
(或最近的约束),因此上述调用将等同于 MyType<obj>.CreateEmpty()
。还是别扭。
为避免这种情况,更好的方法是使用同名模块:
module MyType =
let createEmpty() = MyType(EmptyType)
let x = MyType.createEmpty()
此模式广泛用于泛型类型。例如,参见 Option
或 List
。