scala - 什么是 scala 证据参数

标签 scala

我一直试图找到什么是证据参数的权威定义,但无济于事,以解决“找不到类型证据参数的隐式值......”的情况。您能否为证据参数的确切含义提供一个很好的解释?

最佳答案

我会尝试发布我自己的答案,稍后再进行改进。让我们从一个励志场景开始,但您可以跳到下面的 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/

相关文章:

java - 如何在 Java 子类中调用 Scala trait 的构造函数?

scala - 使用我项目中的自定义 sbt 插件

scala - 从检查点重新启动后 Spark Streaming 选项卡消失

scala - 如何在 Scala 和 Apache Spark 中连接两个 DataFrame?

scala - flatMap 行为在 2.10.0 中发生了变化

scala - SBT Scala版本警告

function - 这是成语 Scala.使用 def 来缩短语句?

scala - 为 Play Framework http 响应创建可写 [Argonaut.Json]

scala - 引用透明度

mysql - 为什么mysql在两个事务同时更新时不以可重复读模式锁定一行?