Разница между Ad-hoc полиморфизмом и параметрическим полиморфизмом в Scala - PullRequest
0 голосов
/ 27 августа 2018

Итак, я искал документацию об основных различиях между parametric polymorphism и adhoc-polymorphism, но у меня все еще есть некоторые сомнения.

Например, такие методы, как head в Collections, являются явно параметрическим полиморфизмом, поскольку код, используемый для получения заголовка в List [Int], такой же, как и в любом другом List.

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

(Не уверен, что это фактическая реализация head, но это не имеет значения)

С другой стороны, классы типов считаются 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 Ответ

0 голосов
/ 27 августа 2018

Метод 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-гизмо), поэтому это специальный полиморфизм. Однако некоторые из неявных методов, которые предоставляют 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.

...