我有这个界面声明
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>
和这个创建对象表达式的函数
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)
}
这很好用。
现在我想将上述类型改造成
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>
与上述几乎相同,只是提取了“搜索方面”
现在我在实现创建对象表达式的函数时
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)
}
我在方法This code is not sufficiently generic. The type variable 'a could not be generalized because it would escape its scope.
上获得了臭名昭着的ReInitWith
这让我发疯了。对于一个我不明白为什么这个看似和其他直接的改变根本就会产生错误,另一方面是什么是试图通信的错误消息?
答案 0 :(得分:5)
第二个示例的一个问题是此ISearchModel
方法包含所有未绑定的泛型类型参数:
abstract ReInitWith: ISearchModel<_, _, _> -> 'target
在第一个示例中,第二个泛型类型绑定到包含接口的'search
类型:
abstract ReInitWith: #IModel<_, 'search, _> -> 'target
如果从第一个示例中删除该类型约束,则无法以完全相同的方式进行编译。
如果您在第一个示例中限制第二个泛型类型,则第二个示例有效:
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
这会为mkSearchModelSimple
生成以下类型签名:
val mkSearchModelSimple :
vctor:(unit -> 'value) ->
sctor:(unit -> 'search) ->
token:string ->
value:'value -> search:'search -> ISearchModelSimple<'value,'search>
注意:我将Token
类型引用替换为string
;它的定义没有提供。