因此,我一直在搜索有关parametric 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
在中间,我们有一些参数化的方法,例如filter,但是我们可以通过提供不同的功能来提供不同的实现。
List(1,2,3).filter(_ % 2 == 0)
// List(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的一些隐式方法实际上本身在参数A
和B
中是参数多态的。因此,除非编译器设法在隐式范围内找到一些非常特殊的临时结构,例如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