什么是 scala 证据参数 [英] What precisely is a scala evidence parameter

查看:37
本文介绍了什么是 scala 证据参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图找到什么是证据参数的权威定义,但无济于事,以解决无法找到类型为证据参数的隐式值......"的情况.你能很好地解释一下证据参数到底是什么吗?

I've been trying to find an authoritative definition of what is an evidence parameter, to no avail, for solving a case of "could not find implicit value for evidence parameter of type....". Can you please provide a very good explanation for what an evidence parameter exactly is?

推荐答案

我会尝试发布我自己的答案,稍后再进行改进.让我们从一个励志场景开始,但您可以跳到下面的 TLDR,然后根据需要返回此处.

I'll try posting my own answer, improving it later as it goes. Let us start with a motivational scenario, but you can jump to the TLDR below then come back here as needed.

在一种情况下,证据参数可以被视为一种通过原始定义之外的某些行为(方法/s)来丰富类的手段.

In one scenario, evidence parameters can be seen as a means of enriching a class with some behavior (method/s) from outside its original definition.

Cake Solutions:

如果您之前没有直观地编写过这样的代码,这里是使用中的证据参数的代码演示.

In case you have not already intuitively written such code before, here's a code demonstration of evidence parameters in use.

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 已在其原始定义之外进行了丰富.然而——只有与证据仪式一起发挥作用的功能才能看到它的丰富.

You might read that code from the bottom up to realize that a class Bar has been enriched outside its original definition. Yet ― only functions that play along with the evidence ceremony can see it as enriched.

这种模式几乎没有什么神奇之处——尽管这是一个独特的语言特性——包装器对象将特征与 Bar 相关联,而 callFoo 依赖于该关联.

There's very little magic going on in this pattern ― although this is a unique language feature ― the wrapper object associates the trait to Bar, and callFoo relies on that association.

我们甚至可以在没有隐式的情况下编写相同的模式,但是最后一行,即调用方法的那一行,将需要一个额外的参数——是否使用隐式的经济性——完全取决于你.

We could even write the same pattern without implicits, but then the last line, the one that calls the method, would need an extra parameter ― the economics of whether to use an implicit or not ― are entirely up to you.

您可以根据需要对其进行加糖或减糖,例如这里有一个小的语法改进:

You can up-sugar or down-sugar it as you wish, for example here's a minor syntax improvement:

(这里只修改了最后一个def,现在去掉注释)

(only the last def herein modified, and the comments removed now)

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 命名任何东西.编译器只知道这是一个证据参数,因为它在所有这些等价情况下的使用方式.

And there's nothing requiring of you to name anything with the string evidence. The compiler just knows this is an evidence parameter by the way it is used in all these equivalent cases.

更一般地或词源学上,借鉴另一个答案,证据参数是一个证据"参数.类型的特定属性,并且编译器需要在方法签名表明此类要求的任何地方(在另一个答案中,没有为 Any 类型提供 <的证据提供:< Foo,这是方法签名所要求的,因此是缺少证据的情况).

More generally or etymologically, borrowing from the other answer, an evidence parameter is one that "evidences" a specific property of a type, and it is required by the compiler wherever a method's signature manifests such a requirement (in the other answer, there is no evidence supplied for type Any being <:< Foo, as required by the method's signature, hence it is a case of a missing evidence).

失败有一个可以作为隐式的证据对象,将导致著名的找不到类型......的证据参数的隐式值,因为编译器知道这是证据模式的一部分,而不仅仅是隐含的缺失(尽管这种差异对您很重要).

Failure to the have an evidence object available as an implicit, will result in the famous could not find implicit value for evidence parameter of type ... because the compiler knows this is part of an evidence pattern and not just a missing implicit (as much as this difference matters to you).

简而言之,某个类 S 的证据参数是一个 T[S] 类型的参数(所以,一个参数是一个类),它定义了一个或者更多关于 S 的东西——因此证据"一些关于 S 的东西——这使得 S 有资格被调用者扩展使用,超出了 S 的原始定义.T[S] 应该具有的确切形状在我上面借用的示例中通过 隐式对象 MakeItFoo 举例说明.

Succinctly speaking, an evidence parameter for some class S is a parameter of a type T[S] (so, a parameter that is a class) that defines one or more things about S ― thus "evidencing" something about S ― that makes S eligible for extended usage by a caller, beyond the original definition of S. The exact shape such a T[S] should have, is exemplified in my borrowed examples above, by implicit object MakeItFoo.

这篇关于什么是 scala 证据参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆