我有这个接口声明
type IModel<'value, 'search, 'target when 'target :> IModel<'value, 'search, 'target>> =
abstract token: string with get
abstract value: 'value with get
abstract search: 'search with get
abstract GetEmpty: unit -> 'target
abstract ReInitWith: #IModel<_, 'search, _> -> 'target
type IModelSimple<'value, 'search> =
inherit IModel<'value, 'search, IModelSimple<'value, 'search>>
abstract Update: ?token:string * ?value: 'value * ?search: 'search -> IModelSimple<'value, 'search>
Run Code Online (Sandbox Code Playgroud)
和这个创建对象表达式的函数
let rec mkModelSimple<'value, 'search> vctor sctor token value search =
{
new IModelSimple<'value, 'search> with
member this.token = token
member this.value = value
member this.search = search
member this.GetEmpty() = mkModelSimple vctor sctor token (vctor()) (sctor())
member this.ReInitWith (m: #IModel<_, 'search, _>) = mkModelSimple vctor sctor m.token this.value m.search
member this.Update(?t:Token, ?v: 'value, ?s: 'search) =
mkModelSimple vctor sctor (defaultArg t this.token) (defaultArg v this.value) (defaultArg s this.search)
}
Run Code Online (Sandbox Code Playgroud)
这很好用.
现在我想将上面的类型改造成
type IModel<'value, 'target when 'target :> IModel<'value, 'target>> =
abstract token: string with get
abstract value: 'value with get
abstract GetEmpty: unit -> 'target
type ISearchModel<'value, 'search, 'target when 'target :> ISearchModel<'value, 'search, 'target>> =
inherit IModel<'value, 'target>
abstract search: 'search with get
abstract ReInitWith: ISearchModel<_, _, _> -> 'target
type ISearchModelSimple<'value, 'search> =
inherit ISearchModel<'value, 'search, ISearchModelSimple<'value, 'search>>
abstract Update: ?token:string * ?value: 'value * ?search: 'search -> ISearchModelSimple<'value, 'search>
Run Code Online (Sandbox Code Playgroud)
与上面几乎相同,只是提取了"搜索方面"
现在我在实现函数时创建对象表达式
let rec mkSearchModelSimple<'value, 'search> vctor sctor token value search =
{
new ISearchModelSimple<'value, 'search> with
member this.token = token
member this.value = value
member this.search = search
member this.GetEmpty() = mkSearchModelSimple vctor sctor token (vctor()) (sctor())
member this.ReInitWith (m: #ISearchModel<_, 'search, _>) = mkSearchModelSimple vctor sctor m.token this.value m.search
member this.Update(?t:Token, ?v: 'value, ?s: 'search) =
mkSearchModelSimple vctor sctor (defaultArg t this.token) (defaultArg v this.value) (defaultArg s this.search)
}
Run Code Online (Sandbox Code Playgroud)
我得到了臭名昭着This code is not sufficiently generic. The type variable 'a could not be generalized because it would escape its scope.的方法ReInitWith
这让我发疯.对于一个我不明白为什么这个看似和其他直接的改变根本就会产生错误,另一方面,尝试通信的错误消息是什么?
第二个示例的一个问题是此ISearchModel方法包含所有未绑定的泛型类型参数:
abstract ReInitWith: ISearchModel<_, _, _> -> 'target
Run Code Online (Sandbox Code Playgroud)
在第一个示例中,第二个泛型类型绑定到包含接口的'search类型:
abstract ReInitWith: #IModel<_, 'search, _> -> 'target
Run Code Online (Sandbox Code Playgroud)
如果从第一个示例中删除该类型约束,则无法以完全相同的方式进行编译.
如果您在第一个示例中限制第二个泛型类型,则第二个示例有效:
type ISearchModel<'value, 'search, 'target when 'target :> ISearchModel<'value, 'search, 'target>> =
inherit IModel<'value, 'target>
abstract search: 'search with get
abstract ReInitWith: ISearchModel<_, 'search, _> -> 'target
Run Code Online (Sandbox Code Playgroud)
这会产生以下类型签名mkSearchModelSimple:
val mkSearchModelSimple :
vctor:(unit -> 'value) ->
sctor:(unit -> 'search) ->
token:string ->
value:'value -> search:'search -> ISearchModelSimple<'value,'search>
Run Code Online (Sandbox Code Playgroud)
注意:我用你的Token类型引用替换了string; 它的定义没有提供.