I would really like to treat scala.collection.immutable.Set[T] as
covariant. It is possible to do this using an implicit conversion, but
I am not sure if this will cause trouble at some point (especially the
asInstanceOf). It seems to work just fine in the REPL though:
scala> val intSet = Set(1,2,3)
intSet: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> val s:Set[Any]=intSet
<console>:8: error: type mismatch;
found : scala.collection.immutable.Set[Int]
required: Set[Any]
Note: Int <: Any, but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Any`. (SLS
3.2.10)
val s:Set[Any]=intSet
^
scala> implicit def setIsCovariant[T,U <: T](s:Set[U]):Set[T] =
s.asInstanceOf[Set[T]]
setIsCovariant: [T, U <: T](s: Set[U])Set[T]
scala> val s:Set[Any]=intSet
s: Set[Any] = Set(1, 2, 3)
scala> val s:Set[String]=intSet
<console>:9: error: type mismatch;
found : scala.collection.immutable.Set[Int]
required: Set[String]
val s:Set[String]=intSet
^
I am only concerned with immutable sets. As far as I know they are
only invariant so they can implement Function1[T,Boolean]. You can of
course use them as an Iterable[T] and get variance, but then you lose
the information that elements can not be contained twice etc.
What I was concerned about is that for example a Set[Int] might not
have a method contains(x:Any) but only a method contains(x:Int). But I
guess due to erasure the signature of the contains method when looking
at it using javap will always be contains(Object x), and even if
@specialized is used at some point there will just be an _additional_
Method contains(int x).
right?
> Set cannot be immutable because it accepts a T in it's "apply" method.
I suppose you meant 'covariant'.
> This *could* mean that it retains T's and if you drop down to Set[Any], it
> could accept any old Any, thereby breaking itself.
I'd really like to see an example for the missbehavor we are fighting
all the time but unfortuanately I cannot produce any. Here is how I've
tried so far:
val s = collection.mutable.Set(1,2)
val sa = s.asInstanceOf[scala.collection.mutable.Set[Any]]
Now I can 'add' Strings or Ints etc. and ask for them by 'apply'
without any error.
sa add 1 // false
sa add 3 // true
sa add "A" // true
sa(4) // false
sa(3) // true
...
What am I missing? Do you have an idea how to demonstrate the devil?
Peter