Note that due the fact of universal equality.
"a" == 1
Should be valid.
Especially, because, you could do this:
val someData: Any = "a"
val otherData: Any = 1
someData == otherData
And that is valid due to liskov.
Something similar happens with contains
.
Whenever or not universal equality is a good or bad idea, or if a typeclass based solution is always better or not. Are two different and long discussions which are better had with a humble attitude, understanding that programming languages are complex projects; where decisions aren’t taken in a vacuum.
Having said that.
While the above is technically correct, everyone agrees that "a" == 1
is always a typo / mistake / error.
As such, the compiler actually tries very hard to be helpful here and avoid instances where the equality check while sound is illogical. For the record, the previously mentioned multiversal equality is another attempt at improving this (but, as everything, it is a trade-off).
However, the compiler can’t catch all the situations where the check is illogical due a lot of reasons. Complexity of that being one, but also that other features of the language go in the opposite way; like union types.
So in one hand you want the compiler to be very strict and catch all errors. But in the other you want the compiler to be flexible enough to infer stuff like A | B
.
As usual with Scala, the langue tries to be in a middle point where is not perfect for anyone but pretty great for everyone.
Additionally also note that type-safe is an spectrum.
e.g.
final case class Point(x: Double, y: Double)
val x = 3.5
val y = 2.1
val point = Point(y, x)
Everything there is typesafe yet the end result is a bug.
Another example:
final case class User(name: String, age: Int)
val luis = User(name = "Luis", age = -27)
Again, a negative age doesn’t make sense.
A fun enough, this language actually can help you avoid these errors, using refined types, opaque types, named arguments, etc.
But, if you try to push it very hard sooner than later you will find that the compiler can’t keep up.
There are actually other languages with even stronger and more powerful type systems. Yet, they see rare to none commercial use. And while there are multiple reasons for that, the main one is that pushing type safety to its limits is usually impractical.
There is a sweet spot where the language can catch a lot of things. But proper automatic testing and code review is still useful.
And, IMHO (and probably the opinions of many others), Scala lives in that middle point, with the possibility of moving both into the stricter and looser direction if you so desire.
The biggest caveat is universal equality, which we all simply learn to deal with.
Final note.
While indeed we all have been bitten by universal equality here and there. At least in my experience, it doesn’t happen that frequently. And for the cases where it matters most there are some alternatives like cats Eq
.
Not wanting to sound rude, and just as a closing comment.
But this is kind of saying: “Well, seatbelts don’t save everyone so I may as well don’t use it”; of course respecting that the contexts are vastly different, but you get the idea.
I do understand where you are coming from. But I hope this and everything else everyone has mentioned kind of help you realize that is not as black-and-white.