在 Scala 中,为什么会出现“无法将多态表达式实例化为预期类型”的问题?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6675419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:12:22  来源:igfitidea点击:

In Scala, why do I get this "polymorphic expression cannot be instantiated to expected type"?

scala

提问by Yang

Why does the following occur in Scala 2.9.0.1?

为什么在 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)
                                            ^

Update: Debilski suggests a better example (not 100% sure this is demonstrating the same underlying phenomenon):

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

Seq(0).toArray : Seq[Int] // compiles
Seq(Some(0)).toArray : Seq[Option[Int]] // doesn't

回答by Daniel C. Sobral

The best person to explain this is Adriaan Moors, and he already did that here on Stack Overflow -- lookup answers from him and you'll find it.

解释这一点的最佳人选是 Adriaan Moors,他已经在 Stack Overflow 上这样做了——从他那里查找答案,你就会找到答案。

Anyway, the problem is that the type of List(Left(0), Right("a")).iterator.toArraycannot be inferred within the boundaries expected by f. It does not conform to Seq[Either[Int, String]]without an implicit conversion, and no implicit conversion can be applied because it (the type) cannot be determined. It's like an egg&chicken problem.

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

If you use <%or assign it to a val, you break the cycle in the inference.

如果您使用<%它或将其分配给一个 val,则会打破推理中的循环。

回答by paradigmatic

This has nothing to do with Eitherbut rather with Arrayhandling. If you convert it manually to a Seqit works:

EitherArray处理无关,而与处理有关。如果您手动将其转换为 aSeq它可以工作:

scala> f(xs.toSeq)
res4: Int = 0

A Scala Arrayis not a Seq(because it is in fact a Java array). But a WappedArrayis. You could also redefine your function fhas:

ScalaArray不是一个Seq(因为它实际上是一个 Java 数组)。但一个WappedArray是。您还可以重新定义您的功能f

scala> def f[A <% Seq[Either[Int,String]]](xs: A) = 0
f: [A](xs: A)(implicit evidence: (A) => Seq[Either[Int,String]])Int

scala> f(xs)
res5: Int = 0

BTW, no need to get an iterator before calling toArray.

顺便说一句,在调用toArray.

回答by Michael Dillon

I believe this is because you cannot turn an Array into an Array, but you can convert a Sequence into an Array. The method wants a Sequence that it can use to make an Array.

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

Bottom line is to check the method signatures and not guess what they are based on the method name.

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

The important part is this:

重要的部分是这样的:

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)

The toArraymethod wants a Seq (so a List would be fine) and it returns an Array. You have passed it an Array and it does not know what to do. Either make the Array into a Seq first, or just skip the toArraymethod entirely.

toArray方法需要一个 Seq(所以一个 List 就可以了)并且它返回一个数组。您已将数组传递给它,但它不知道该怎么做。要么先将 Array 变成 Seq,要么完全跳过该toArray方法。

If you go back one step it is clear that the iteratormethod takes your List and returns an Array. Each method invocation is a function call.

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