找不到 scala.reflect.ClassManifest[T] 类型的证据参数的隐式值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14796390/
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 04:57:07  来源:igfitidea点击:

Could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T]

scalatypes

提问by dmitry

It seems I don't understand something important, maybe about erasure (damn it).

似乎我不明白一些重要的事情,也许是关于擦除(该死)。

I have a method, which I wanted to create array of size nfilled with values from gen:

我有一个方法,我想创建一个大小数组,其中n填充了以下值gen

def testArray[T](n: Int, gen: =>T) {
  val arr = Array.fill(n)(gen)
  ...
}

And use it, for example as:

并使用它,例如:

testArray(10, util.Random.nextInt(10))

But I get error:

但我得到错误:

scala: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T]
val arr = Array.fill(n)(gen)
                       ^

Please, explain what I did wrong, why this error, and what kind of code it makes impossible?

请解释我做错了什么,为什么会出现这个错误,以及它使什么样的代码变得不可能?

采纳答案by drexin

That is because in testArraythe concrete type of Tis not known at compile time. Your signature has to look like def testArray[T : ClassManifest](n: Int, gen: =>T), this will add an implicit parameter of type ClassManifest[T]to your method, that is automatically passed to the call of testArrayand then further passed to the Array.fillcall. This is called a context bound.

那是因为在编译时不知道testArray具体类型T。您的签名必须看起来像def testArray[T : ClassManifest](n: Int, gen: =>T),这将向ClassManifest[T]您的方法添加一个隐式类型的参数,该参数会自动传递给 的调用,testArray然后进一步传递给Array.fill调用。这称为context bound.

回答by EECOLOR

The Array.fillmethod has the following signature:

Array.fill方法具有以下签名:

def fill[T](n: Int)(elem: => T)(implicit arg0: ClassManifest[T]): Array[T]

In order to get an instance of ClassManifest[T]you need to know the concrete type. A ClassManifestcan be obtained like this:

为了得到一个实例,ClassManifest[T]你需要知道具体的类型。AClassManifest可以这样获得:

implicitly[ClassManifest[String]]

A ClassManifestis implicitly available for every concrete type.

AClassManifest隐式可用于每个具体类型。

For any impliciterror, you can add the implicits you require to the method with the type parameter:

对于任何implicit错误,您可以使用 type 参数将所需的隐式添加到方法中:

def wrap[T](n:Int)(elem: => T)(implicit c:ClassManifest[T], o:Ordering[T])

If you did not yourself introduce ClassManifestor Ordering, the writers of the library have (most likely) provided sensible defaults for you.

如果您没有自己介绍ClassManifestOrdering,图书馆的作者(很可能)为您提供了合理的默认值。

If you would call the wrapmethod:

如果您要调用该wrap方法:

wrap(2)(3)

It's expanded like this:

它是这样展开的:

wrap[Int](2)(3)(implicitly[ClassManifest[Int]], implicitly[Ordering[Int]])

If you introduced a custom class Personhere, you would get an error for not finding an implicit instance of Ordering[Person]. The writers of the library could not have known how to order Person. You could solve that like this:

如果您Person在此处引入了自定义类,则会因为找不到Ordering[Person]. 图书馆的作者不可能知道如何订购Person。你可以这样解决:

class Person

implicit val o = new Ordering[Person] { // implement required methods }

wrap(2)(new Person)

The Scala compiler looks in different scopes for implicits, an Orderingwould usually not be specified like this. I suggest you look up implicit resolution on the internet to learn more about it.

Scala 编译器在不同的范围内查找隐式,Ordering通常不会像这样指定。我建议您在互联网上查找隐式分辨率以了解更多信息。