Reputation: 333
We define a customEquality[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
}
}
The following code works, as expected:
Seq("a").view should contain theSameElementsInOrderAs Seq("A")
Now, we add a custom Equality
for 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
}
}
Custom TripleEquals
equality works for Seq
:
assert(Seq("a") === Seq("A"))
but does not work for SeqView
:
assert(Seq("a").view === Seq("A"))
Exception in thread "main" org.scalatest.exceptions.TestFailedException: SeqView("a") did not equal List("A")
Why?
Upvotes: 2
Views: 718
Reputation: 39366
If you look at what .view
returns:
def view(from: Int, until: Int): SeqView[A, Seq[A]]
you see that SeqView[_, _]
actually has two type parameters, so it is not conforming to your specification SEQ[e] <: GenSeq[e]
. (In theory you could imagine that if Scala supported partially-applied type constructors this could be unified somehow, but it is a tricky problem and Scala does not support it).
In your case, you can make it work by making a definition that is explicit for SeqView
and does not use higher-kinded types:
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
}
}
Though, I admit this is somewhat unsatisfying.
Upvotes: 1