容器的最新隐式平等

时间:2015-08-21 09:15:30

标签: scala scalatest

我们定义了自定义Equality[String]

implicit val upperCaseEquality = new Equality[String] {
  override def areEqual(self: String, b: Any): Boolean = b match {
    case other: String => self.toUpperCase == other.toUpperCase
    case _ => false
  }
}

以下代码正常运行:

Seq("a").view should contain theSameElementsInOrderAs Seq("A")

现在,我们为Equality添加了自定义Seq

implicit def SeqEquality[T, SEQ[e] <: GenSeq[e]](implicit equality: Equality[T]): Equality[SEQ[T]] = new Equality[SEQ[T]] {
  override def areEqual(self: SEQ[T], b: Any): Boolean = b match {
    case other: GenSeq[_] => self.size == other.size && self.zip(other).forall(equality.areEqual _ tupled)
    case _ => false
    }
}

自定义TripleEquals平等适用于Seq

assert(Seq("a") === Seq("A"))

但不适用于SeqView

assert(Seq("a").view === Seq("A"))

Exception in thread "main" org.scalatest.exceptions.TestFailedException: SeqView("a") did not equal List("A")

为什么?

1 个答案:

答案 0 :(得分:1)

如果你看what .view returns

def view(from: Int, until: Int): SeqView[A, Seq[A]]

您发现SeqView[_, _]实际上有两个类型参数,因此它不符合您的规范SEQ[e] <: GenSeq[e]。 (理论上你可以想象,如果Scala支持部分应用的类型构造函数,这可能会以某种方式统一,但这是一个棘手的问题而Scala不支持它。)

在您的情况下,您可以通过为SeqView明确定义并且不使用更高级别的类型来使其工作:

implicit def SeqViewEquality[T](implicit equality: Equality[T]): Equality[SeqView[T, Seq[T]]] = new Equality[SeqView[T, Seq[T]]] {
  override def areEqual(self: SeqView[T, Seq[T]], b: Any): Boolean = b match {
    case other: GenSeq[_] => self.size == other.size && self.zip(other).forall(equality.areEqual _ tupled)
    case _ => false
  }
}

虽然,我承认这有点令人不满意。