Skip to content

Instantly share code, notes, and snippets.

@jrudolph
Created September 8, 2014 11:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrudolph/5c66f4c28381d4452519 to your computer and use it in GitHub Desktop.
Save jrudolph/5c66f4c28381d4452519 to your computer and use it in GitHub Desktop.
Not so covariant sets
scala> class MySet[T](elements: Seq[T])(implicit ordering: Ordering[T]) extends scala.collection.immutable.Set[T] {
| // Members declared in scala.collection.GenSetLike
| def iterator: Iterator[T] = elements.iterator
|
| // Members declared in scala.collection.SetLike
| def -(elem: T): scala.collection.immutable.Set[T] = ???
| def +(elem: T): scala.collection.immutable.Set[T] = ???
|
| def contains(t: T): Boolean = elements.exists(ordering.equiv(t, _))
| }
defined class MySet
scala>
scala> import scala.annotation.unchecked.uncheckedVariance
import scala.annotation.unchecked.uncheckedVariance
scala>
scala> class T[+A: Ordering](elements: Seq[A]) extends MySet[A @uncheckedVariance](elements)
defined class T
scala>
scala> val ints = new T(Seq(1, 2, 3, 4, 5))
ints: T[Int] = Set(1, 2, 3, 4, 5)
scala>
scala> val cov: T[Any] = ints
cov: T[Any] = Set(1, 2, 3, 4, 5)
scala>
scala> cov.contains("1")
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
at scala.math.Ordering$Int$.compare(Ordering.scala:256)
at scala.math.Ordering$class.equiv(Ordering.scala:100)
at scala.math.Ordering$Int$.equiv(Ordering.scala:256)
at MySet$$anonfun$contains$1.apply(<console>:15)
at MySet$$anonfun$contains$1.apply(<console>:15)
at scala.collection.LinearSeqOptimized$class.exists(LinearSeqOptimized.scala:80)
at scala.collection.immutable.List.exists(List.scala:84)
at MySet.contains(<console>:15)
at .<init>(<console>:13)
at .<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)
at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983)
at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:573)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568)
at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:745)
at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:790)
at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:702)
at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:566)
at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:573)
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:576)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:867)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822)
at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135)
at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:822)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:83)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment