Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does empty List equality work?

Does the == operator really compare List by content? Especially with regards to empty List?

The following comparisons work as expected

List("A", "B", "C") == "ABC".split("").toList // true
List() == List() // true
List.empty[String] == List.empty[String] // true

However, empty list comparison of different type gives confusing result:

List.empty[String] == List.empty[Int] // true: on different types?

EDIT: in the initial question, I made a misleading test case which has been clarified by Andrey. Thanks. Reproduced here

val emptyStrSplit = "".split("").toList // List("") and not List() as displayed in Console
List.empty[String] == emptyStrSplit // false: b/c List() != List("")
like image 263
Polymerase Avatar asked Jul 21 '26 10:07

Polymerase


1 Answers

  • List.empty[String] is the singleton object Nil, which extends List[Nothing] (covariantly, subtype of List[String]).
  • List.empty[Int] is the singleton object Nil, which extends List[Nothing] (covariantly, subtype of List[Int]).
  • Every singleton object is equal to itself.
  • Therefore, Nil == Nil gives true.

So, essentially, you have a single object Nil which is simultaneously of type List[String] and of type List[Int]. That's what you get if you have subtyping. I don't see anything strange or contradictory here.

If you want to ensure that the types are the same, you can use implicit evidence of type A =:= B with default value null, and then check whether a non-null evidence is provided by the compiler:

def eqSameType[A, B](a: A, b: B)(implicit ev: A =:= B = null) = 
  if (ev == null) false else a == b

Example:

scala> eqSameType(List.empty[Int], List.empty[String])
res4: Boolean = false
like image 144
Andrey Tyukin Avatar answered Jul 23 '26 22:07

Andrey Tyukin