为什么在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)
^
更新:Debilski建议了一个更好的例子(不是100%确定这是在演示相同的潜在现象):
Seq(0).toArray : Seq[Int] // compiles
Seq(Some(0)).toArray : Seq[Option[Int]] // doesn't
发布于 2011-07-14 02:02:40
最能解释这一点的人是Adriaan Moors,他已经在Stack Overflow上做到了这一点--查找他的答案,你就会找到它。
无论如何,问题是无法在f
期望的边界内推断出List(Left(0), Right("a")).iterator.toArray
的类型。如果不进行隐式转换,则不符合Seq[Either[Int, String]]
,并且无法确定它(类型),因此无法应用隐式转换。这就像是一个鸡蛋和鸡的问题。
如果您使用<%
或将其分配给val,则会中断推理中的循环。
发布于 2011-07-13 17:29:32
这与Either
无关,而是与Array
处理有关。如果您手动将其转换为Seq
,它将起作用:
scala> f(xs.toSeq)
res4: Int = 0
Scala不是Seq
(因为它实际上是一个Array
数组)。但WappedArray
才是。您还可以重新定义f
具有的函数:
scala> def f[A <% Seq[Either[Int,String]]](xs: A) = 0
f: [A](xs: A)(implicit evidence$1: (A) => Seq[Either[Int,String]])Int
scala> f(xs)
res5: Int = 0
顺便说一句,在调用toArray
之前不需要获取迭代器。
发布于 2011-07-13 16:34:35
我相信这是因为您不能将数组转换为数组,但可以将序列转换为数组。该方法需要一个可用于生成数组的序列。
底线是检查方法签名,而不是根据方法名称猜测它们是什么。
重要的部分是:
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)
toArray
方法需要一个Seq (所以List就可以了),它返回一个数组。你给它传递了一个数组,它不知道该怎么做。或者先将数组转换为序列,或者完全跳过toArray
方法。
如果后退一步,很明显iterator
方法会获取列表并返回一个数组。每个方法调用都是一个函数调用。
https://stackoverflow.com/questions/6675419
复制相似问题