我一直在寻找有关“证据参数”是什么的权威定义,但无果,因为要解决“找不到隐式值类型为...的证据参数”的问题。请问您能否提供一个非常好的解释,说明证据参数究竟是什么?
我一直在寻找有关“证据参数”是什么的权威定义,但无果,因为要解决“找不到隐式值类型为...的证据参数”的问题。请问您能否提供一个非常好的解释,说明证据参数究竟是什么?
object EvidenceExample {
// class with no methods
case class Bar(value: String)
// a trait the class Bar had not implemented
trait WithFoo[A] {
def foo(x: A): String
}
// object that attaches an implementation of the trait for Bar - for methods
// willing to play along with this kind of trait attachment - see immediately below
implicit object MakeItFoo extends WithFoo[Bar] {
def foo(x: Bar) = x.value
}
// method willing to recognize anything as having trait WithFoo,
// as long as it has evidence that it does - the evidence being the previous object
def callFoo[A](thing: A)(implicit evidence: WithFoo[A]) = evidence.foo(thing)
callFoo(Bar("hi")) // and it works
}
Bar
的类在其原始定义之外被丰富了。然而,只有与证据仪式相符的函数才能看到它被丰富了。Bar
,而callFoo
依赖于该关联。def
,并删除了注释)object EquivalentEvidenceExample {
case class Bar(value: String)
// a trait the class Bar had not implemented
trait WithFoo[A] {
def foo(x: A): String
}
implicit object MakeItFoo extends WithFoo[Bar] {
def foo(x: Bar) = x.value
}
def callFoo[A:WithFoo](thing: A) = implicitly[WithFoo[A]].foo(thing) // lightly sugared syntax, frankly only more confusing
callFoo(Bar("hi"))
}
并没有要求您使用字符串evidence
来命名任何内容。编译器只是通过它在所有等效情况下的使用方式知道这是一个证据参数。
更一般地说,或者从词源上来说,借鉴自其他答案,证据参数是指“证明”类型特定属性的参数,并且在方法签名表现出这种要求的地方,编译器需要它(在其他答案中,没有提供类型Any
是<:< Foo
的证据,因此存在缺失证据的情况)。
没有可用的隐式证据对象将导致著名的could not find implicit value for evidence parameter of type ...
,因为编译器知道这是证据模式的一部分,而不仅仅是缺少隐式(无论这种区别对您有多重要)。
S
,其证据参数是一种类型为T[S]
的参数(即一个类),它定义了关于S
的一个或多个内容——从而“证明”了关于S
的一些东西——这使得调用方可以将S
用于扩展使用,超出原始定义范围。这样的T[S]
应该具有的确切形式,在我借用的上面的例子中,由implicit object MakeItFoo
说明。通过这种语法糖,您可以获得规范称之为“evidence参数”的合成参数。(请注意,这也涵盖了现已弃用的视图边界方法或非特质类的类型参数
A
也可以具有一个或多个上下文边界A:T
。在这种情况下,类型参数可以实例化为任何类型S
,只要在实例化点存在证据,表明S
满足绑定T
。这样的证据包括一个具有类型T[S]
的隐式值。
<%
)。
由于经常明确写出隐含参数也被称为"evidence",所以如果它证明了类型的特定属性,我认为任何隐含参数都可以称为"evidence"。
例如,<:< [A, B]
表明 A
是 B
的子类型。
trait Foo
trait Bar[A] {
def baz(implicit evidence: A <:< Foo): Unit
}
然后如果你尝试这样做:
trait Test {
def bar: Bar[Any]
bar.baz
}
这会导致编译错误:
<console>:58: error: Cannot prove that Any <:< Foo.
bar.baz
^
implicitNotFound
注释来指定。如果没有具体的代码示例,就不清楚是什么生成了“无法找到类型为...的证明参数的隐式值”。@annotation.implicitNotFound(msg = "Oh noes! No type class for ${A}")
trait MyTypeClass[A]
trait Bar[A] {
def baz(implicit evidence: MyTypeClass[A]): Unit
}
然后:
trait Test {
def bar: Bar[Any]
bar.baz
}
<console>:58: error: Oh noes! No type class for Any
bar.baz
^
def foo[A: M](implicit b: B): C
// expands to:
// def foo[A](implicit evidence$1: M[A], b: B): C
更多细节请参见规格说明。 https://www.scala-lang.org/files/archive/spec/2.11/07-implicits.html