scala - Scala 中 Ad-hoc 多态性和参数多态性的区别

标签 scala functional-programming polymorphism parametric-polymorphism adhoc-polymorphism

因此,我一直在搜索有关参数多态性adhoc-polymorphism 之间主要区别的文档,但我仍然有一些疑问。

例如,集合中的 head 等方法显然是参数多态性,因为用于获取 List[Int] 中的头部的代码与任何其他 List 中的代码相同。

List[T] {
    def head: T = this match {
        case x :: xs => x
        case Nil => throw new RuntimeException("Head of empty List.") 
    }
}

(不确定这是否是 head 的实际实现,但没关系)

另一方面,类型类被认为是临时多态性。由于我们可以根据类型提供不同的实现。

trait Expression[T] {
    def evaluate(expr: T): Int
}

object ExpressionEvaluator {
  def evaluate[T: Expression](value: T): Int = implicitly[Expression[T]].evaluate(value)
}

implicit val intExpression: Expression[Int] = new Expression[Int] {
  override def evaluate(expr: Int): Int = expr
}

ExpressionEvaluator.evaluate(5)
// 5

在中间,我们有像过滤器这样的参数化方法,但我们可以通过提供不同的功能来提供不同的实现。

List(1,2,3).filter(_ % 2 == 0)
// List(2)

像 filter、map 等方法是否被认为是临时多态性?为什么或为什么不?

最佳答案

List 上的方法filter 是参数多态性的一个例子。签名是

def filter(p: (A) ⇒ Boolean): List[A] 

它对所有类型 A 的工作方式完全相同。因为它可以被任何类型A参数化,所以它是普通的参数多态性。

map 这样的方法同时使用了这两种类型的多态性。

map 的完整签名是:

final def map[B, That]
  (f: (A) ⇒ B)
  (implicit bf: CanBuildFrom[List[A], B, That])
: That  

此方法依赖于隐式值(CBF-gizmo)的存在,因此它是临时多态性。但是,某些提供正确类型的 CBF 的隐式方法实际上本身在 AB 类型中是参数多态的。因此,除非编译器设法在隐式作用域中找到一些非常特殊的临时构造,例如 CanBuildFrom[List[String], Int, BitSet],否则它迟早会退回到类似

implicit def ahComeOnGiveUpAndJustBuildAList[A, B]
: CanBuildFrom[List[A], B, List[B]]

因此,我认为可以说这是一种“混合参数临时多态性”,它首先尝试找到最合适的临时类型类 CanBuildFrom[List[A], B, That] 在隐式范围内,但最终会退回到普通的参数多态性,并返回一个万能的 CanBuildFrom[List[A], B, List[B]]-在 AB 中都是参数多态的解决方案。

关于scala - Scala 中 Ad-hoc 多态性和参数多态性的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52044766/

相关文章:

java - 查找是否至少有一个 - Observable Java 8 Rx

.net - .NET 中的声明性线程安全

java - 使用父类(super class)中已在子类中重写的方法,具体取决于调用它的对象的类型

scala - 找不到 Apache Spark Mongo-Hadoop 连接器类

design-patterns - 设计模式和 Scala

scala - 如何在play框架中的scala模板中声明和访问局部变量?

ruby - Ruby 是否执行尾调用优化?

python - 在使用 OOP 尝试钻石形状问题时,Python 中发生了什么

c++ - 嵌套结构属性继承

Scala:带有列表和选项的函数中的无名参数