在Scala中,为什么我会将这个"多态表达式无法实例化为预期类型"?

Yan*_*ang 22 scala

为什么在Scala 2.9.0.1中会出现以下情况?

scala> def f(xs: Seq[Either[Int,String]]) = 0
f: (xs: Seq[Either[Int,String]])Int

scala> val xs = List(Left(0), Right("a")).iterator.toArray
xs: Array[Product with Serializable with Either[Int,java.lang.String]] = Array(Left(0), Right(a))

scala> f(xs)
res39: Int = 0

scala> f(List(Left(0), Right("a")).iterator.toArray)
<console>:9: error: polymorphic expression cannot be instantiated to expected type;
 found   : [B >: Product with Serializable with Either[Int,java.lang.String]]Array[B]
 required: Seq[Either[Int,String]]
       f(List(Left(0), Right("a")).iterator.toArray)
                                            ^
Run Code Online (Sandbox Code Playgroud)

更新:Debilski提出了一个更好的例子(不是100%肯定这表明了相同的潜在现象):

Seq(0).toArray : Seq[Int] // compiles
Seq(Some(0)).toArray : Seq[Option[Int]] // doesn't
Run Code Online (Sandbox Code Playgroud)

Dan*_*ral 5

解释这个的最好的人是Adriaan Moors,他已经在Stack Overflow上做了这个 - 从他那里查找答案,你会发现它.

无论如何,问题是List(Left(0), Right("a")).iterator.toArray无法在预期的范围内推断出类型f.如果没有Seq[Either[Int, String]]隐式转换,它就不符合,并且不能应用隐式转换,因为它(类型)无法确定.这就像鸡蛋和鸡肉问题.

如果您使用<%或将其分配给val,则会破坏推理中的循环.


Mic*_*lon 2

我相信这是因为你不能将数组转换为数组,但你可以将序列转换为数组。该方法需要一个可用于创建数组的序列。

底线是检查方法签名,而不是根据方法名称猜测它们是什么。

重要的部分是:

found   : [B >: Product with Serializable with Either[Int,java.lang.String]]Array[B]
 required: Seq[Either[Int,String]]
       f(List(Left(0), Right("a")).iterator.toArray)
Run Code Online (Sandbox Code Playgroud)

toArray方法需要一个 Seq(因此列表就可以了)并且它返回一个数组。你给它传递了一个数组,但它不知道要做什么。要么先将数组变成 Seq,要么toArray完全跳过该方法。

如果您返回一步,很明显该iterator方法采用您的列表并返回一个数组。每个方法调用都是一个函数调用。