我一直卡在IntelliJ(14.1.5)的Scala(2.11.7)编译器错误现在几个小时。我已经谷歌搜索,扼杀了我的大脑,并尝试了大量的变化,但似乎无法绕过它。为什么我会收到“类型参数...不符合特性......”编译器错误的错误?
我已经采取了代码上下文,并尽可能小地剪裁它(包括删除任何外部库依赖项)以捕获我一直用来尝试缩小问题的域。我以为我使用的是非常直接的惯用Scala;情况下的物体,与类型参数性状等
从开始abstract case class CoordinateRadian
最后一行的第四个是一个产生这个Scala编译错误:
Error:(128, 129) type arguments [Test.this.CoordinateRadian.unitBase.type,Test.this.LongitudeRadian,Test.this.LatitudeRadian] do not conform to trait Coordinate's type parameter bounds [U <: Test.this.Angle.UnitBase.Member,+O <: Test.this.Longitude[U],+A <: Test.this.Latitude[U]] abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, LongitudeRadian, LatitudeRadian] {
下面是与编译器错误的代码:
package org.public_domain
class Test {
object Angle {
object UnitBase {
trait Member
case object RADIAN extends Member
case object DEGREE extends Member
}
trait UnitBase[U <: Angle.UnitBase.Member] {
def unitBase: U
}
object ZeroBase {
trait Member
case object LEFT extends Member
case object MIDDLE extends Member
}
trait ZeroBase[U <: Angle.UnitBase.Member, Z <: Angle.ZeroBase.Member] extends Angle.UnitBase[U] {
def zeroBase: Z
}
}
trait Angle[U <: Angle.UnitBase.Member, Z <: Angle.ZeroBase.Member] extends Angle.ZeroBase[U, Z] {
def theta: Double
}
trait Angle__ObjectBase {
def basesAsTuple: (Angle.UnitBase.Member, Angle.ZeroBase.Member)
}
object AngleRadianMiddle extends ((Double) => AngleRadianMiddle) with Angle__ObjectBase {
val basesAsTuple: (Angle.UnitBase.Member, Angle.ZeroBase.Member) =
(Angle.UnitBase.RADIAN, Angle.ZeroBase.MIDDLE)
def apply(theta: Double): AngleRadianMiddle =
new AngleRadianMiddle(theta) {
def unitBase =
basesAsTuple._1
def zeroBase =
basesAsTuple._2
private def readResolve(): Object =
AngleRadianMiddle(theta)
def copy(thetaNew: Double = theta): AngleRadianMiddle =
AngleRadianMiddle(thetaNew)
}
}
abstract case class AngleRadianMiddle private[AngleRadianMiddle] (theta: Double) extends Angle[AngleRadianMiddle.basesAsTuple._1.type, AngleRadianMiddle.basesAsTuple._2.type] {
def copy(thetaNew: Double = theta): AngleRadianMiddle
}
trait Itude[U <: Angle.UnitBase.Member] extends Angle[U, Angle.ZeroBase.MIDDLE.type] {
val zeroBase =
Angle.ZeroBase.MIDDLE
}
sealed trait Longitude[U <: Angle.UnitBase.Member] extends Itude[U]
sealed trait Latitude[U <: Angle.UnitBase.Member] extends Itude[U]
object LongitudeRadian extends ((Double) => LongitudeRadian) {
val basesAsTuple: (Angle.UnitBase.Member, Angle.ZeroBase.Member) =
(Angle.UnitBase.RADIAN, Angle.ZeroBase.MIDDLE)
def apply(theta: Double): LongitudeRadian =
new LongitudeRadian(theta) {
def unitBase =
basesAsTuple._1
private def readResolve(): Object =
LongitudeRadian(theta)
def copy(thetaNew: Double = theta): LongitudeRadian =
LongitudeRadian(thetaNew)
}
}
abstract case class LongitudeRadian(theta: Double) extends Longitude[LongitudeRadian.basesAsTuple._1.type] {
def copy(thetaNew: Double = theta): LongitudeRadian
}
object LatitudeRadian extends ((Double) => LatitudeRadian) {
val basesAsTuple: (Angle.UnitBase.Member, Angle.ZeroBase.Member) =
(Angle.UnitBase.RADIAN, Angle.ZeroBase.MIDDLE)
def apply(theta: Double): LatitudeRadian =
new LatitudeRadian(theta) {
def unitBase =
basesAsTuple._1
private def readResolve(): Object =
LatitudeRadian(theta)
def copy(thetaNew: Double = theta): LatitudeRadian =
LatitudeRadian(thetaNew)
}
}
abstract case class LatitudeRadian(theta: Double) extends Latitude[LatitudeRadian.basesAsTuple._1.type] {
def copy(thetaNew: Double = theta): LatitudeRadian
}
trait Coordinate[U <: Angle.UnitBase.Member, +O <: Longitude[U], +A <: Latitude[U]] {
def longitude: O
def latitude: A
val x: O =
longitude
val y: A =
latitude
}
object CoordinateRadian extends ((LongitudeRadian, LatitudeRadian) => CoordinateRadian) {
val unitBase: Angle.UnitBase.Member =
Angle.UnitBase.RADIAN
def apply(longitude: LongitudeRadian, latitude: LatitudeRadian): CoordinateRadian =
new CoordinateRadian(longitude, latitude) {
private def readResolve(): Object =
CoordinateRadian(longitude, latitude)
def copy(longitudeNew: LongitudeRadian = longitude, latitudeNew: LatitudeRadian = latitude): CoordinateRadian =
CoordinateRadian(longitudeNew, latitudeNew)
}
}
//abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, Longitude[CoordinateRadian.unitBase.type], Latitude[CoordinateRadian.unitBase.type]] {
abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, LongitudeRadian, LatitudeRadian] {
def copy(longitudeNew: LongitudeRadian = longitude, latitudeNew: LatitudeRadian = latitude): CoordinateRadian
}
}
您会注意到文件末尾的第五行是一个注释掉的行(与文件末尾的第四行非常相似)。如果从端线取消对第五,然后注释掉从端线的第四和编译代码(“全部构建”中的IntelliJ),两个错误会发出:
Error:(125, 67) overriding method longitude in trait Coordinate of type => Test.this.Longitude[Test.this.CoordinateRadian.unitBase.type]; value longitude has incompatible type abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, Longitude[CoordinateRadian.unitBase.type], Latitude[CoordinateRadian.unitBase.type]] {
Error:(125, 95) overriding method latitude in trait Coordinate of type => Test.this.Latitude[Test.this.CoordinateRadian.unitBase.type]; value latitude has incompatible type abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, Longitude[CoordinateRadian.unitBase.type], Latitude[CoordinateRadian.unitBase.type]] {
我可能只是工作在这太久了,现在有一个黄疸的眼睛。我还没有想到在一个多小时内有任何新的方法来解决这个问题。所以,对于我做错什么的指导将不胜感激。
太棒了! Tysvm!我非常感谢你的回答。当然,它会引发下一个问题......为什么我在这些声明中重复完全相同的类型信息(如果标识是身份...)会导致编译器变得困惑?我遇到了很多编译器问题的另一个方向(错误地推断类型),我赞成在默认情况下指定类型。现在即使过度指定(以身份为基础)也会导致编译器问题,这是相当令人沮丧的。 – chaotic3quilibrium
你是如何在冥府中找到答案的?是什么让你认为去基地AsTuple和unitBase的类型超标?我只是试图通过我将来如何为自己做同样的事情。你是否有一些额外的工具,你正在使用的表面更多的是什么编译器正在做什么,它是困惑,导致你这些特定的声明?这不是我曾经考虑过的路线(根据我的身份假设)。 – chaotic3quilibrium
正如我所说的,只要查看“坐标”的约束条件和“CoordinateRadian”和“LatitudeRadian”的类型参数就可以清楚地说明问题。您不是“重复相同的信息”:编译器推断例如'val basesAsTuple:(Angle.UnitBase.RADIAN.type,Angle.ZeroBase.MIDDLE。类型)'在'LatitudeRadian'中,_not_'val basesAsTuple:(Angle.UnitBase.Member,Angle.ZeroBase.Member)'。所以它知道'LatitudeRadian.basesAsTuple._1'是'Angle.UnitBase.RADIAN'和'LatitudeRadian.basesAsTuple._1.type'与'Angle.UnitBase.RADIAN.type'是相同的,这就是约束所要求的。 –