scala, неявный в определении типа функции

У меня есть следующий абстрактный класс:

abstract class FieldProvider[+T: Writes](db: DB)(implicit i: RequestAction, j: ExecutionContext) {}

и следующие реализации:

class LengthProvider extends FieldProvider ...

object LengthProvider extends ((DB) => LengthProvider) {
  def apply(v1: DB): LengthProvider = new LengthProvider(v1)
}

class WidthProvider extends FieldProvider ...

object WidthProvider extends ((DB) => WidthProvider) {
  def apply(v1: DB): WidthProvider = new WidthProvider(v1)
}

Причина, по которой у меня есть эти методы apply, заключается в том, что мне нужна следующая карта конфигурации:

val providers: Map[String, ((DB) => FieldProvider)] = Map(
 "length" -> LengthProvider,
 "width"  -> WidthProvider
)

Чтобы я мог инициализировать провайдеров строкой, содержащей их имя:

providers("length")(db) // returns a new instance of LengthProvider

Теперь моя проблема в том, что все эти конструкторы провайдеров требуют двух неявных переменных. Но я не знаю, как включить его в определение функции (DB) => FieldProvider. Итак, по сути, сигнатура метода apply должна быть чем-то вроде (DB)(implicit RequestAction, ExecutionContext) => FieldProvider, но я не знаю, есть ли правильный синтаксис для того, что я пытаюсь сделать.

Я также мог бы отказаться и передать их явно:

object WidthProvider extends ((DB, RequestAction, ExecutionContext) => WidthProvider) {
   def apply(v1: DB, v2: RequestAction, v3: ExecutionContext): WidthProvider = new WidthProvider(v1)(v2,v3)
}

Но тогда мне придется передавать их явно в другом месте, вместо providers("length")(db) мне придется писать providers("length")(db, implicitly[RequestAction], implicitly[ExecutionContext]), что кажется неправильным.


person roman-roman    schedule 12.04.2016    source источник
comment
Вы перемещаете вещи, которым нужны имплициты, в более низкую область, внутри реализации LengthProvider. Вместо того, чтобы использовать их в качестве аргументов конструктора, вы используете подход для каждого метода.   -  person flavian    schedule 12.04.2016
comment
Что ж, это помогло. Не стесняйтесь публиковать это как ответ, я приму его.   -  person roman-roman    schedule 12.04.2016
comment
Возможный дубликат типизации scala требует неявного   -  person cchantep    schedule 12.04.2016
comment
Базовая кодовая база действительно одна и та же, но вопросы разные, и предлагаемые решения разные.   -  person roman-roman    schedule 12.04.2016


Ответы (2)


Предположим, что FieldProvider имеет 2 метода, которым нужны имплициты. Более удобный способ избежать дублирования — передать их как неявные аргументы уровня конструктора, и тогда все внутренние методы в FieldProvider смогут «разделять» их.

Однако это не поможет в вашем текущем дереве классов, поэтому, чтобы исправить это, вместо того, чтобы делать:

abstract class FieldProvider()(implicit param1: X1..) {
  def test: T = param1.doSomething
}

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

abstract class FieldProvider() {
  def test()(implicit param1: X1): T = param1.doSomething
}
person flavian    schedule 13.04.2016

Итак, по сути, сигнатура метода apply должна быть чем-то вроде (DB)(implicit RequestAction, ExecutionContext) => FieldProvider, но я не знаю, есть ли правильный синтаксис для того, что я пытаюсь сделать.

Обратите внимание, что вы можете напрямую получить (в будущей версии Scala 2017) неявный тип функции.

См. запрос на включение 1775 от сам Одерский.

Давайте немного помассируем определение f1, переместив последний раздел параметра справа от знака равенства:

def f1(x: Int) = { implicit thisTransaction: Transaction =>
  thisTransaction.println(s"first step: $x")
  f2(x + 1)
}

Правая часть этой новой версии f1 теперь является неявным значением функции.
Какого типа это значение?
Раньше это было Transaction => Int, то есть информация о том, что функция имеет неявный параметр, была утеряна. в типе.

Основное расширение, реализованное запросом на вытягивание, заключается во введении неявных типов функций, которые отражают значения неявных функций, которые у нас уже есть.
Конкретно, новый тип f1:

implicit Transaction => Int

Точно так же, как обычный синтаксис типа функции A => B, уменьшает сахар до scala.Function1[A, B], синтаксис неявного типа функции implicit A => B уменьшает сахар до scala.ImplicitFunction1[A, B].
То же самое справедливо и для других типов функций. После объединения запроса на вытягивание #1758 верхнего предела в 22 больше нет. такие функции.

person VonC    schedule 10.12.2016