Of course you don't really want to change the semantics of tuples, because the universe would implode. You just want something like tuples -- except for their equality semantics.
Why not just use a case class? Tuples are really just ready-made classes to hold a few things together when it isn't worth the trouble to define a class. Well, if you want to change equality, I'd say it's worth the trouble! Plus you can use more meaningful names than _1 and _2.
I don't know what those names would be, of course, but here's some code. As Travis points out, messing with equality is tricky, in part because you also have to think about the hash code. Hopefully this is reasonable:
scala> case class Foo[T]( a:T, b:T ) {
override def equals( that:Any ) = that match {
case that:Foo[T] => ( that canEqual this ) && (
this.a == that.a && this.b == that.b ||
this.a == that.b && this.b == that.a
)
case _ => false
}
override def canEqual( that:Any ) = that.isInstanceOf[Foo[T]]
override def hashCode = a.hashCode + b.hashCode
}
defined class Foo
scala> Foo(1,2) == Foo(1,2)
res15: Boolean = true
scala> Foo(1,2) == Foo(2,1)
res16: Boolean = true
scala> Foo(1,2) == Foo(2,2)
res17: Boolean = false
scala> collection.immutable.HashSet( Foo(0,1), Foo(1,0), Foo(1,2) )
res18: scala.collection.immutable.HashSet[Foo[Int]] = Set(Foo(0,1), Foo(1,2))
Note that res18
contains Foo(1,0)
but not Foo(0,1)
because of that definition of equality.