如何推断Fbound参数化类型?

时间:2016-02-22 01:02:54

标签: scala types f-bounded-polymorphism

我有一个f-bound类型和依赖它的其他类型。我很难以一种不需要为操作明确指定fbound的方式来声明它们。详细信息在示例中

object WhatIWant {
  sealed trait FBound[F <: FBound[F]]
  sealed trait Dep[F <: FBound[F]]
  final case class Holder[F <: FBound[F]](name : String, dep : Dep[F])

  final class SimpleBound extends FBound[SimpleBound]
  final case class SimpleDep(data : Int) extends Dep[SimpleBound]

  object Usage {
    def extract(holder : Holder[SimpleBound]) : Int =
      holder.dep.data

    def enclose(dep : SimpleDep) : Unit = {
      val holder = Holder("sample", dep)
    }
  }

  object DoNotWant {
    def extract(holder : Holder[SimpleBound]) : Int =
      holder.dep.asInstanceOf[SimpleDep].data // explicit type specification

    def enclose(dep : SimpleDep) : Unit = {
      val holder = Holder[SimpleBound]("sample", dep) // explicit type specification
    }
  }
}

编译器按预期给出错误:

TypeParam.scala:13: error: value data is not a member of param.WhatIWant.Dep[param.WhatIWant.SimpleBound]
      holder.dep.data

这完全有道理。并非所有可能的Dep[SimpleBound]实现都是SimpleDep(并且编译器太笨了而无法考虑sealed修饰符)

然后我尝试了另一种方法:

object WhatITry {
  sealed trait FBound[F <: FBound[F]] {
    type FDep <: Dep[F]
  }
  sealed trait Dep[F <: FBound[F]]
  final case class Holder[F <: FBound[F]](name : String, dep : F#FDep)

  final class SimpleBound extends FBound[SimpleBound] {
    override type FDep = SimpleDep
  }
  final case class SimpleDep(data : Int) extends Dep[SimpleBound]

  object Usage {
    def extract(holder : Holder[SimpleBound]) : Int =
      holder.dep.data

    def enclose(dep : SimpleDep) : Unit = {
      val holder = Holder("sample", dep)
    }
  }
}

也不好:

TypeParam.scala:47: error: type mismatch;
 found   : dep.type (with underlying type param.WhatITry.SimpleDep)
 required: ?#FDep
Note that SimpleDep extends Any, not AnyRef.
Such types can participate in value classes, but instances
cannot appear in singleton types or in reference comparisons.
      val holder = Holder("sample", dep)

我尝试了更多方法:

object TrySelfType {       密封性状FBound [F&lt ;:FBound [F]] {this:F =&gt;         输入FDep&lt;:Dep [F]       }       密封性状Dep [F&lt ;:FBound [F]] {this:F#FDep =&gt; }       最终案例类持有人[F&lt;:FBound [F]](姓名:String,dep:Dep [F])

  final class SimpleBound extends FBound[SimpleBound] {
    override type FDep = SimpleDep
  }
  final case class SimpleDep(data : Int) extends Dep[SimpleBound]

  object Usage {
    def extract(holder : Holder[SimpleBound]) : Int =
      holder.dep.data

    def enclose(dep : SimpleDep) : Unit = {
      val holder = Holder("sample", dep)
    }
  }
}

object TryAbstract {
  sealed trait FBound[F <: FBound[F]] { this : F =>
    type FDep <: Dep.TPE[F]
  }
  object FBound {
    type Any = FBound[F] forSome {type F <: FBound[F]}
  }

  sealed trait Dep {
    type MyF <: FBound.Any
  }
  object Dep {
    type TPE[F <: FBound[F]] = Dep { type MyF <: F }
  }

  final case class Holder[F <: FBound[F]](name : String, dep : F#FDep)

  final class SimpleBound extends FBound[SimpleBound] {
    override type FDep = SimpleDep
  }
  final case class SimpleDep(data : Int) extends Dep {
    override type MyF = SimpleBound
  }

  object Usage {
    def extract(holder : Holder[SimpleBound]) : Int =
      holder.dep.data

    def enclose(dep : SimpleDep) : Unit = {
      val holder = Holder("sample", dep)
    }
  }
}

object TryWith {
  sealed trait FBound[F <: FBound[F]] {
    type FDep <: Dep[F]
  }
  sealed trait Dep[F <: FBound[F]]
  object Dep {
    type TPE[F <: FBound[F]] = Dep[F] with F#FDep
  }
  final case class Holder[F <: FBound[F]](name : String, dep : Dep.TPE[F])

  final class SimpleBound extends FBound[SimpleBound] {
    override type FDep = SimpleDep
  }
  final case class SimpleDep(data : Int) extends Dep[SimpleBound]

  object Usage {
    def extract(holder : Holder[SimpleBound]) : Int =
      holder.dep.data

    def enclose(dep : SimpleDep) : Unit = {
      val holder = Holder("sample", dep)
    }
  }
}

object TryAbstractExtra {
  sealed trait FBound[F <: FBound[F]] { this : F =>
    type FDep <: Dep.TPE[F]
  }
  object FBound {
    type Any = FBound[F] forSome {type F <: FBound[F]}
  }

  sealed trait Dep {
    type MyF <: FBound.Any
  }
  object Dep {
    type TPE[F <: FBound[F]] = Dep { type MyF <: F }
  }

  final case class Holder[F <: FBound[F]](name : String, dep : F#FDep)
  def holder(name : String, dep : Dep) = Holder[dep.MyF](name, dep)

  final class SimpleBound extends FBound[SimpleBound] {
    override type FDep = SimpleDep
  }
  final case class SimpleDep(data : Int) extends Dep {
    override type MyF = SimpleBound
  }

  object Usage {
    def extract(holder : Holder[SimpleBound]) : Int =
      holder.dep.data

    def enclose(dep : SimpleDep) : Unit = {
      val hld = holder("sample", dep)
    }
  }
}

但他们也失败了:

TypeParam.scala:66: error: value data is not a member of param.TrySelfType.Dep[param.TrySelfType.SimpleBound]
      holder.dep.data
             ^
TypeParam.scala:103: error: type mismatch;
 found   : dep.type (with underlying type param.TryAbstract.SimpleDep)
 required: ?#FDep
Note that SimpleDep extends Any, not AnyRef.
Such types can participate in value classes, but instances
cannot appear in singleton types or in reference comparisons.
      val holder = Holder("sample", dep)
                                ^
TypeParam.scala:128: error: type mismatch;
 found   : dep.type (with underlying type param.TryWith.SimpleDep)
 required: param.TryWith.Dep.TPE[?]
    (which expands to)  param.TryWith.Dep[?] with ?#FDep
      val holder = Holder("sample", dep)
                                ^
TypeParam.scala:149: error: type arguments [dep.MyF] do not conform to method apply's type parameter bounds [F <: param.TryAbstractExtra.FBound[F]]
  def holder(name : String, dep : Dep) = Holder[dep.MyF](name, dep)

我理解为什么编译器会抱怨(除了最后一个具有误导性描述的错误)。我正在寻找解决问题的方法,而不是解释为什么所有这些方法都失败了。我把它们写下来说明我已经搜索过的方向。

0 个答案:

没有答案