【问题标题】:Scalatest implicit Equality for ContainersScalatest 容器的隐式相等
【发布时间】:2015-08-22 00:14:16
【问题描述】:

我们定义一个自定义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")

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

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")

为什么?

【问题讨论】:

    标签: scala scalatest


    【解决方案1】:

    如果你看what .view returns

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

    你看到SeqView[_, _]实际上有两个类型参数,所以它不符合你的规范SEQ[e] &lt;: 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
      }
    }
    

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

    【讨论】:

      猜你喜欢
      • 2020-07-12
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多