函数类型定义中隐含的scala

scala implicit in function type definition

我有以下摘要class:

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]),这感觉不对。

让我们假设 FieldProvider 有 2 个方法需要隐式。避免重复的更方便的方法是将它们作为构造函数级别的隐式参数传递,然后 FieldProvider 中的所有内部方法都可以 "share" 它们。

但是,这对您当前的 class 树没有帮助,因此要解决此问题,请不要执行以下操作:

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

只需将隐式移动到方法级别,这样您就可以在不同于扩展构造函数的时间提供它。

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

So, essentially, the apply method signature should be something like (DB)(implicit RequestAction, ExecutionContext) => FieldProvider, but I don't know if there is a correct syntax for what I'm trying to do.

请注意,您可能会直接获得(在未来的 Scala 2017 版本中)implicit function type.

pull request 1775, by Odersky本人。

Let’s massage the definition of f1 a bit by moving the last parameter section to the right of the equals sign:

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

The right hand side of this new version of f1 is now an implicit function value.
What’s the type of this value?
Previously, it was Transaction => Int, that is, the knowledge that the function has an implicit parameter got lost in the type.

The main extension implemented by the pull request is to introduce implicit function types that mirror the implicit function values which we have already.
Concretely, the new type of f1 is:

implicit Transaction => Int

Just like the normal function type syntax A => B, desugars to scala.Function1[A, B], the implicit function type syntax implicit A => B desugars to scala.ImplicitFunction1[A, B].
The same holds at other function arities. With dotty’s pull request #1758 merged, there is no longer an upper limit of 22 for such functions.