Scala中Ad-hoc多态与参数多态的区别

时间:2018-08-27 18:07:14

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

因此,我一直在搜索有关parametric polymorphismadhoc-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

在中间,我们有一些参数化的方法,例如filter,但是我们可以通过提供不同的功能来提供不同的实现。

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

过滤器,地图等方法是否被视为即席多态性?为什么或为什么不呢?

2 个答案:

答案 0 :(得分:3)

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

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

所有类型A的工作方式完全相同。由于可以通过任何类型的A对其进行参数化,因此它是普通的 parameter 多态性。

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]]A中参数多态的全拟合B解。

答案 1 :(得分:0)

请参见以下幻灯片,详细了解Scala中的即席多态性:https://www.slideshare.net/pjschwarz/ad-hoc-polymorphism-using-type-classes-and-cats

enter image description here