【问题标题】:Constructing three level deep F-Bound types构造三层深 F-Bound 类型
【发布时间】:2015-04-17 13:11:43
【问题描述】:

我有三个 F-Bound 类型ABC,其中BA 参数化,CB 参数化(因此也由@987654329 参数化) @)。我可以实例化AB,但是当我尝试实例化C 时,编译器无法推断类型。如果我明确地给它类型,一切正常 - 但这些类型丢失似乎很愚蠢(这是由于类型擦除吗?)。

sealed trait A[AA <: A[AA]] {
  self =>
  val data: String
}

case class AInst(data: String) extends A[AInst]

sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
  self: BB =>
  val content: AA
}

case class BInst[AA <: A[AA]](content: AA) extends B[BInst[AA], AA]

sealed trait C[CC <: C[CC, BB, AA], BB <: B[BB, AA], AA <: A[AA]] {
  self: CC =>
  val content: BB
}

case class CInst[BB <: B[BB, AA], AA <: A[AA]](content: BB) 
     extends C[CInst[BB, AA], BB, AA]

val a1 = new AInst("A1")
val b1 = BInst(a1)
val c1 = CInst[BInst[AInst],AInst](b1)

是否有解决方法,我不必专门指定 CInst 的类型?

我目前正在使用类型参数化来实现 F-Bounds,但是切换到抽象类型成员会解决这个问题吗?那时的班级会是什么样子?

【问题讨论】:

标签: scala parametric-polymorphism self-type


【解决方案1】:

怎么样:

... //A,AInst,B,BInst without changes

sealed trait C[CC <: C[CC, BB, AA], BB <: B[BB, AA], AA <: A[AA]] {
  self: CC =>
  val content: B[BB, AA] //`B[BB, AA]` instead of `BB`
}

case class CInst[BB <: B[BB, AA], AA <: A[AA]](content: B[BB,AA]) extends C[CInst[BB, AA], BB, AA]

用法:

scala> val a1 = new AInst("A1")
a1: AInst = AInst(A1)

scala> val b1 = BInst(a1)
b1: BInst[AInst] = BInst(AInst(A1))

scala> val c1 = CInst(b1)
c1: CInst[BInst[AInst],AInst] = CInst(BInst(AInst(A1)))

在编译器将BB 视为BInst[AA &lt;: A[AA]] 之前它不起作用,所以我的B[BB,AA] 刚刚将BB 提升为B[BInst[AInst], AInst]

附:对于类型成员,您仍然会以某种方式将类型传递给您的案例类,因此没有太大区别。

【讨论】:

  • 太好了,谢谢!我是如此接近......类型定义变得有点笨拙,我想知道这是否也是一种代码味道。
  • 这取决于您如何看待它们 :) 我将它们视为编译时 defs like here。但是compile'r type inferrence可能不是很清楚,实际上它很大程度上取决于你的领域逻辑,你可能真的不需要它们
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-18
  • 2010-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多