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