Ad-hoc полиморфизм - классы типов

Я просмотрел руководство по скалязу.

Из этой ссылки я понимаю следующий код:

scala> def sum[A](xs: List[A])(implicit m: Monoid[A]): A = xs.foldLeft(m.mzero)(m.mappend)
sum: [A](xs: List[A])(implicit m: Monoid[A])A

scala> implicit val intMonoid = IntMonoid
intMonoid: IntMonoid.type = IntMonoid$@3387dfac

scala> sum(List(1, 2, 3, 4))
res9: Int = 10

Но я не понимаю следующий код:

scala> def sum[A: Monoid](xs: List[A]): A = {
         val m = implicitly[Monoid[A]]
         xs.foldLeft(m.mzero)(m.mappend)
       }
sum: [A](xs: List[A])(implicit evidence$1: Monoid[A])A

scala> sum(List(1, 2, 3, 4))
res10: Int = 10

Если мы рассмотрим List(1, 2, 3, 4), A - это Int.

Итак, как мы можем иметь A Monoid и A Int в def sum[A: Monoid](xs: List[A]): A = {?

Спасибо


person ccheneson    schedule 31.08.2014    source источник


Ответы (1)


Синтаксис A : X называется "контекстной привязкой", и он эквивалентен получению неявного параметра типа X[A]. То есть следующие два объявления одинаковы:

def sum[A: Monoid](xs: List[A]): A
def sum[A](xs: List[A])(implicit $ev0: Monoid[A]): A

Однако имя неявного параметра недоступно при использовании границ контекста, поэтому вам нужно «получить» его, если вам нужно использовать его напрямую. Один из способов сделать это - использовать метод implicitly, как показано ниже:

val m = implicitly[Monoid[A]]

Вот определение implicitly:

def implicitly[T](implicit v: T): T = v

В любом случае, два определения, которые вы показали, почти одинаковы. Если вы понимаете первый, просто знайте, что второй идентичен, но написан с другим синтаксисом.

Последнее замечание о границах контекста: может показаться глупым использовать синтаксис, связанный с контекстом, только для того, чтобы впоследствии использовать implicitly для получения имени параметра. Но если вам просто нужно, чтобы неявный параметр передавался как неявный другим методам - ​​и, следовательно, не нужно знать имя - это делает объявления намного более аккуратными.

person Daniel C. Sobral    schedule 31.08.2014