接受的答案对我来说非常不满意,因为我仍然不知道发生了什么。
我的第一反应是,它一定是隐含+推理的错误,无论他们是否知道。
问题不在于,例如,类型参数 for map
,因为它减少到匹配:
scala> def f[X: Ordering](seq: Seq[X]) = seq match { case List(a,b) => b > a }
这怎么可能行不通?我的猜测是它与 Ordered 的不变性有关,因此将 List.unapply 解包的方式与输入 Seq 进行比较意味着我们不能依赖范围内的隐式 Ordering。
让我们打开一些调试。(-Xprint:typer、patmat、-Xlog-implicits、-Yinfer-debug)
case Seq
在 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)
在 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()
};
换句话说,unapply
只是返回你的 Seq,它会得到前两个元素。
应该看起来完全一样,case List
除了它没有类型检查。
好的,我被其他事情分心了,比如我女儿今天开始在水下游泳,所以为了短路,这行得通:
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
也许这种赤字在起作用。