1

我现在在 IntelliJ (14.1.5) 中遇到 Scala (2.11.7) 编译器错误已经好几个小时了。我在 Google 上搜索过,绞尽脑汁并尝试了很多变化,但似乎无法绕过它。

我已经获取了代码上下​​文并尽可能地将其剪裁得尽可能小(包括剪裁任何外部库依赖项)以捕获我一直用来尝试缩小问题范围的域。我以为我使用的是非常简单的惯用 Scala;案例对象,带有类型参数的特征等。

从最后一行开始的第四行abstract case class CoordinateRadian是产生这个 Scala 编译器错误的那个:

错误:(128, 129) 类型参数 [Test.this.CoordinateRadian.unitBase.type,Test.this.LongitudeRadian,Test.this.LatitudeRadian] 不符合特征坐标的类型参数边界 [U <: Test.this.Angle .UnitBase.Member,+O <: Test.this.Longitude[U],+A <: Test.this.Latitude[U]] 抽象案例类 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 中的“Build All”),将发出两个错误:

错误:(125, 67) 在 trait Coordinate of type => Test.this.Longitude[Test.this.CoordinateRadian.unitBase.type] 中覆盖方法经度;值经度具有不兼容的类型抽象案例类 CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, Longitude[CoordinateRadian.unitBase.type], Latitude[CoordinateRadian.unitBase.type]] {

错误:(125, 95) 在 trait Coordinate of type => Test.this.Latitude[Test.this.CoordinateRadian.unitBase.type] 中覆盖方法纬度;值 latitude 具有不兼容的类型 abstract case class CoordinateRadian private[CoordinateRadian] (longitude: LongitudeRadian, latitude: LatitudeRadian) extends Coordinate[CoordinateRadian.unitBase.type, Longitude[CoordinateRadian.unitBase.type], Latitude[CoordinateRadian.unitBase.type]] {

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

4

1 回答 1

1

Coordinate好吧,通过对您需要的约束LongitudeRadian <: Longitude[CoordinateRadian.unitBase.type](对于纬度也是如此),这是错误的,因为LatitudeRadian.basesAsTuple._1.type它不是CoordinateRadian.unitBase.type(编译器只知道它LatitudeRadian.basesAsTuple._1是一个Angle.UnitBase.Member)的子类型。如果您只是从basesAsTupleand中删除类型注释unitBase,编译器将毫无问题地推断出单例类型

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]

等等。被编译器咬住的机会要少得多,因为无法证明两个对象是相同的。

于 2015-10-07T19:45:57.767 回答