2015-10-07 47 views
1

我一直卡在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]] {

我可能只是工作在这太久了,现在有一个黄疸的眼睛。我还没有想到在一个多小时内有任何新的方法来解决这个问题。所以,对于我做错什么的指导将不胜感激。

回答

1

好了,通过在Coordinate约束,你需要有LongitudeRadian <: Longitude[CoordinateRadian.unitBase.type](以及类似纬度),这是错误的,因为LatitudeRadian.basesAsTuple._1.type不是CoordinateRadian.unitBase.type亚型(编译器知道只有LatitudeRadian.basesAsTuple._1Angle.UnitBase.Member)。如果您只从basesAsTupleunitBase中删除类型注释,编译器will infer the singleton types without problems

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.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.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.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.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 
    } 
} 

但说实话,这看起来像过度使用单身类型给我。我不明白你为什么需要unitBasebasesAsTuple。我宁愿写

abstract case class LongitudeRadian(theta: Double) extends Longitude[RADIAN.type] 

abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[RADIAN.type, LongitudeRadian, LatitudeRadian] 

等等被编译器咬住无法证明两个对象的机会是相同的。

+0

太棒了! Tysvm!我非常感谢你的回答。当然,它会引发下一个问题......为什么我在这些声明中重复完全相同的类型信息(如果标识是身份...)会导致编译器变得困惑?我遇到了很多编译器问题的另一个方向(错误地推断类型),我赞成在默认情况下指定类型。现在即使过度指定(以身份为基础)也会导致编译器问题,这是相当令人沮丧的。 – chaotic3quilibrium

+0

你是如何在冥府中找到答案的?是什么让你认为去基地AsTuple和unitBase的类型超标?我只是试图通过我将来如何为自己做同样的事情。你是否有一些额外的工具,你正在使用的表面更多的是什么编译器正在做什么,它是困惑,导致你这些特定的声明?这不是我曾经考虑过的路线(根据我的身份假设)。 – chaotic3quilibrium

+0

正如我所说的,只要查看“坐标”的约束条件和“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'是相同的,这就是约束所要求的。 –

相关问题