2016-04-12 2 views
1

У меня следующий абстрактный класса: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]), который не чувствует правильно.

+0

Вы перемещаете вещи, которые нуждаются в имплицитах, в меньшую область действия внутри реализации 'LengthProvider'. Вместо того, чтобы использовать их как аргументы конструктора, вы применяете метод для каждого метода. – flavian

+0

Ну, это помогло. Не стесняйтесь публиковать его в качестве ответа, я соглашусь с ним. –

+0

Возможный дубликат [scala typing require implicit] (http://stackoverflow.com/questions/36569881/scala-typing-require-implicit) – cchantep

ответ

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 
} 
0

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

Обратите внимание, что вы можете непосредственно получить (в будущей версии Scala 2017 года) в implicit function type.

См. pull request 1775, по Odersky.

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

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

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

Главное расширение, реализуемое запросом на растяжение, заключается в представлении неявных типов функций, которые отражают значения неявных функций, которые у нас уже есть.
В частности, новый тип Ф1:

implicit Transaction => Int 

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

Смежные вопросы