如何让编译器在此示例中插入正确的类型?

时间:2018-02-15 18:06:21

标签: f#

这是对此问题How can I get rid of this "Can not be generalised" error?

的某种跟进

给出以下类型

type IModel<'value, 'target when 'target :> IModel<'value, 'target>> =
    abstract value: 'value with get

type IModelSimple<'value, 'target> =
    inherit IModel<'value, IModelSimple<'value, 'target>>
    abstract ReInitWith:  #IModel<_ , _ > -> 'target

并且此函数返回一个对象表达式

let rec mkModelSimple<'value, 'target> vctor value =
    {
        new IModelSimple<'value, 'target> with
            member this.value = value
            member this.ReInitWith m = mkModelSimple vctor this.value
    }

我收到此错误

Type mismatch. Expecting a
    ''target'
but given a
    'IModelSimple<'value,'target>'

执行ReInitWith

1 个答案:

答案 0 :(得分:3)

正如编译器报告的那样,您正在定义一个函数,其中推断类型包含自身并且将是无限的。解决这个问题的方法是引入一些打破递归的命名类型。一种选择是使用递归类型定义新记录:

type IModel<'value, 'target when 'target :> IModel<'value, 'target>> =
    abstract value: 'value with get

type IModelSimple<'value, 'target> =
    inherit IModel<'value, IModelSimple<'value, 'target>>
    abstract ReInitWith :  #IModel<_, _> -> 'target

type Model<'value, 'target> =
  { Model : IModelSimple<'value, Model<'value, 'target>> }

let rec mkModelSimple<'value, 'target> vctor value =
    { Model = 
        { new IModelSimple<'value, Model<'value, 'target>> with
              member this.value = value
              member this.ReInitWith m = 
                mkModelSimple<_, _> vctor this.value } }

仅仅是为了记录,我认为这段代码非常难以理解。它肯定会延伸仿制药的合理性,我建议在生产中避免做这样的事情。