繁体   English   中英

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

[英]Difference between Ad-hoc polymorphism and Parametric polymorphism in Scala

所以,我一直在搜索关于parametric polymorphismadhoc-polymorphism之间主要区别的文档,但我仍然有一些疑问。

例如,像集合中的head方法显然是参数多态性,因为用于获取 List[Int] 中的 head 的代码与任何其他 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)

过滤器、映射等方法是否被视为临时多态性? 为什么或者为什么不?

List s上的方法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)的存在,因此它是ad-hoc多态。 然而,提供正确类型的CBF的一些隐式方法实际上在类型AB本身是参数化多态的。 因此,除非编译器设法在隐式作用域中找到一些非常特殊的ad-hoc构造,如CanBuildFrom[List[String], Int, BitSet] ,否则它迟早会回归到像

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

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

有关 Scala 中的临时多态性的精彩介绍,请参阅以下幻灯片: https : //www.slideshare.net/pjschwarz/ad-hoc-polymorphism-using-type-classes-and-cats

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM