Scala 2.8 CanBuildFrom

Следуя еще одному вопросу, который я задал, прорыв Scala 2.8 , я хотел узнать немного больше о методе Scala TraversableLike[A].map чья подпись такова:

 def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That 

Обратите внимание на несколько вещей об этом методе:

  • Требуется функция, поворачивающая каждый A в проходящей в B
  • Он возвращает That и принимает неявный аргумент типа CanBuildFrom[Repr, B, That] .

Я могу назвать это следующим образом:

 > val s: Set[Int] = List("Paris", "London").map(_.length) s: Set[Int] Set(5,6) 

То, что я не могу понять, заключается в том, что компилятор реализует тот факт, что That привязано к B (то есть, это некоторая коллекция B). Параметры типа выглядят не зависимыми как от подписи выше, так и от сигнатуры признака CanBuildFrom :

 trait CanBuildFrom[-From, -Elem, +To] 

Как компилятор Scala гарантирует, что That невозможно заставить во что-то, что не имеет смысла?

 > val s: Set[String] = List("Paris", "London").map(_.length) //will not compile 

Как компилятор решает, какие неявные объекты CanBuildFrom находятся в области вызова?

Обратите внимание, что второй аргумент для map является неявным аргументом. Должна быть неявная область действия с соответствующими типами, или, в противном случае, вы должны передать такой аргумент.

В вашем примере That должен быть Set[String] , B должен быть Int и Repr должен быть List[String] . Поэтому для компиляции вам нужен следующий неявный объект в области видимости:

 implicit object X: CanBuildFrom[List[String], Int, Set[String]] 

В сфере нет такой вещи. Кроме того, breakOut не может предоставить его, потому что сам он нуждается в неявном CanBuildFrom , первым типом которого может быть любой class (контравариантный потомок Nothing ), но в противном случае он ограничен другими типами.

Посмотрите, например, на фабрику CanBuildFrom из сопутствующего объекта List :

 implicit def canBuildFrom [A] : CanBuildFrom[List, A, List[A]] 

Поскольку он связывает второй и третий параметры через A , подразумеваемый вопрос не будет работать.

Итак, как узнать, где искать, в отношении таких имплицитов? Прежде всего, Scala импортирует несколько вещей во все области. Сейчас я могу вспомнить следующий импорт:

 import scala.package._ // Package object import scala.Predef._ // Object // import scala.LowPriorityImplicits, class inherited by Predef import scala.runtime._ // Package 

Поскольку мы обеспокоены имплицитами, обратите внимание, что при импорте вещей из пакетов единственными возможными могут быть синглтоны. С другой стороны, когда вы импортируете объекты из объектов (одноточечных), вы можете иметь неявные определения, значения и одиночные числа.

Прямо сейчас есть CanBuildFrom implicits внутри Predef и LowPriorityImplicits , которые связаны со строками. Они позволяют нам написать "this is a string" map (_.toInt) .

Таким образом, запрет этих автоматических импорта и явный импорт вы делаете, где еще можно найти неявное? Одно место: объекты-компаньоны экземпляра, на который применяется метод.

Я говорю сопутствующий объект s во множественном числе, потому что сопутствующие объекты всех признаков и classов, унаследованные classом рассматриваемого экземпляра, могут содержать соответствующие импликации. Я не уверен, что сам экземпляр может содержать неявный. Честно говоря, я не могу воспроизвести это прямо сейчас, поэтому я, конечно, ошибаюсь.

Во всяком случае, загляните внутрь объектов-компаньонов.

 object ArrayBuffer extends SeqFactory[ArrayBuffer] { /** $genericCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ArrayBuffer[A]] = new GenericCanBuildFrom[A] def newBuilder[A]: Builder[A, ArrayBuffer[A]] = new ArrayBuffer[A] } 
Interesting Posts

Как удалить вредоносные программы-шпионы, вредоносное ПО, рекламное ПО, вирусы, трояны или руткиты с моего ПК?

Удалить элемент из словаря, когда его ключ неизвестен

Получение привязки Ссылка в URL для ASP.Net

Почему в инициализаторах classа можно использовать = или {}?

Как я могу сохранить новые строки в частичной части AngularJS?

Позволяя клавише «Ввод» нажать кнопку «Отправить», в отличие от использования только MouseClick

Как получить данные об авариях из моего приложения Android?

Есть ли способ, которым я могу поделиться 3,42 ГБ загрузки Windows 8.1 из Windows Store?

В чем разница между ./ и ../?

CSS Media Query – Soft-клавиатура нарушает правила ориентации CSS – альтернативное решение?

Почему «extern const int n» не работает должным образом?

Как перенаправить указатель с другого controllerа?

Полоса пробела от выхода jsp

Как закрепить два списка по-разному?

Поддержка gzip в Spark

Давайте будем гением компьютера.