我一直试图找到什么是证据参数的权威定义,但无济于事,以解决“找不到类型证据参数的隐式值......”的情况。您能否为证据参数的确切含义提供一个很好的解释?
最佳答案
我会尝试发布我自己的答案,稍后再进行改进。让我们从一个励志场景开始,但您可以跳到下面的 TLDR,然后根据需要返回此处。
在一种情况下,证据参数可以被看作是一种通过原始定义之外的某些行为(方法)来丰富类的手段。
对 Cake Solutions 上的好帖子的温和复述:
如果您之前没有直观地编写过这样的代码,这里是使用中的证据参数的代码演示。
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
命名任何内容。编译器只知道这是一个证据参数,因为它在所有这些等价情况下的使用方式。更一般地或更从词源学上讲, borrowing from the other answer ,一个证据参数是一个“证明”类型的特定属性的参数,编译器需要在方法签名表明这种要求的任何地方(在另一个答案中,没有提供证据)类型
Any
是 <:< Foo
,这是方法签名所要求的,因此是缺少证据的情况)。未能将证据对象作为隐式可用,将导致著名的
could not find implicit value for evidence parameter of type ...
,因为编译器知道这是证据模式的一部分,而不仅仅是缺失的隐式(尽管这种差异对您很重要)。域名注册地址:
简而言之,某个类
S
的证据参数是 T[S]
类型的参数(因此,一个类的参数)定义了关于 S
的一个或多个事物——因此“证明”了关于 S
的一些东西,使得 x114 有资格扩展为 x114调用者的用法,超出 S
的原始定义。 S
应该具有的确切形状在我上面借用的示例中以 T[S]
为例。
关于scala - 什么是 scala 证据参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34499663/