Разница между Ad-hoc полиморфизмом и параметрическим полиморфизмом в Scala
Итак, я искал документацию о главном разнице между 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.")
}
}
(Не уверен, что это фактическая реализация головы, но это не имеет значения)
С другой стороны, классы типов считаются adhoc-полиморфизмом. Так как мы можем предоставить различные реализации, привязанные к типам.
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)
Являются ли такие методы, как фильтр, карта и т. Д., Специальным полиморфизмом? Почему или почему нет?
1 ответ
Метод filter
на List
s является примером параметрического полиморфизма. Подпись
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 правильного типа, на самом деле сами по себе параметрически полиморфны в типах. 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
,
См. Следующую презентацию для отличного введения в специальный полиморфизм в Scala: https://www.slideshare.net/pjschwarz/ad-hoc-polymorphism-using-type-classes-and-cats