【问题标题】:scala implicit in function type definition函数类型定义中隐含的scala
【发布时间】:2016-08-03 07:43:34
【问题描述】:

我有以下抽象类:

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

【问题讨论】:

  • 您将需要隐式的东西移到较低的范围内,在 LengthProvider 实现中。您不必将它们作为构造函数参数,而是执行每个方法的方法。
  • 嗯,这有帮助。随意发布它作为答案,我会接受它。
  • 底层代码确实是一样的,只是问题不同,提出的解决方案也不同。

标签: scala playframework playframework-2.0 scala-implicits


【解决方案1】:

假设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
}

【讨论】:

    【解决方案2】:

    所以,本质上,apply 方法签名应该类似于(DB)(implicit RequestAction, ExecutionContext) => FieldProvider,但我不知道我正在尝试做的事情是否有正确的语法。

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

    pull request 1775Odersky 本人。

    让我们将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]
    这同样适用于其他函数。合并dotty’s pull request #1758 后,此类函数的上限不再为 22。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-04
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      • 2016-06-24
      • 1970-01-01
      • 1970-01-01
      • 2020-07-22
      相关资源
      最近更新 更多