The accepted answer is pretty unsatisfying to me, in the sense that I still don't know what's going on.
My first reaction is, It must a bug with implicits + inference, whether it's something they know about yet or not.
The problem doesn't reside in, say, the type param for map
, since it reduces to the match:
scala> def f[X: Ordering](seq: Seq[X]) = seq match { case List(a,b) => b > a }
How can that not work? My speculation is that it will have to do with the invariance of Ordered, so that the way List.unapply is unpacked is compared to the input Seq means we can't rely on the implicit Ordering in scope.
Let's turn on some debug. (-Xprint:typer,patmat, -Xlog-implicits, -Yinfer-debug)
This is how the case Seq
is translated at typer:
def f[A](seq: Seq[A])(implicit evidence$1: Ordering[A]): Boolean = seq match {
case collection.this.Seq.unapplySeq[A](<unapply-selector>) <unapply> ((a @ _), (b @ _)) => scala.`package`.Ordering.Implicits.infixOrderingOps[A](b)(evidence$1).>(a)
and at patmat:
def f[A](seq: Seq[A])(implicit evidence$1: Ordering[A]): Boolean = {
case <synthetic> val x1: Seq[A] = seq;
case5(){
<synthetic> val o7: Option[Seq[A]] = collection.this.Seq.unapplySeq[A](x1);
if (o7.isEmpty.unary_!)
if (o7.get.!=(null).&&(o7.get.lengthCompare(2).==(0)))
{
val a: A = o7.get.apply(0);
val b: A = o7.get.apply(1);
matchEnd4(scala.`package`.Ordering.Implicits.infixOrderingOps[A](b)(evidence$1).>(a))
}
else
case6()
else
case6()
};
In other words, the unapply
just gives back your Seq, and it gets the first two elements.
The case List
should look exactly the same, except it doesn't type check.
OK, I got distracted by other things, like my daughter started swimming underwater today, so to short-circuit, this works:
scala> import Ordering.Implicits.infixOrderingOps
import Ordering.Implicits.infixOrderingOps
scala> import reflect.ClassTag
import reflect.ClassTag
scala> def f[X](seq: Seq[X])(implicit e1: Ordering[X], e2: ClassTag[X]) = seq match { case xs: List[X] if xs.length == 2 => xs(1) > xs(0) }
f: [X](seq: Seq[X])(implicit e1: Ordering[X], implicit e2: scala.reflect.ClassTag[X])Boolean
Maybe this deficit is at play.