scala隐含在函数类型定义中

时间:2016-04-12 15:23:36

标签: scala playframework playframework-2.0 scala-implicits

我有以下抽象类:

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

2 个答案:

答案 0 :(得分:2)

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

但是,这对您当前的类树没有帮助,所以要解决这个问题,而不是这样做:

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

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

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

答案 1 :(得分:0)

  

所以,基本上,{"links":{"first":"http://localhost:8000/api/equipments?page=1","last":"http://localhost:8000/api/equipments?page=1","next":null,"prev":null},"data":[{"type":"equipment","id":"1","attributes":{"name":"Mh-x25","fabricator":"Stairville","storeplace":12,"labor":"L","max_quantity":8,"status":"OK"},"relationships":{"event":{"data":[{"type":"Assignment","id":"24"},{"type":"Assignment","id":"25"}]}}},{"type":"equipment","id":"2","attributes":{"name":"Road Hog 4","fabricator":"HES","storeplace":12,"labor":"L","max_quantity":1,"status":"im Lager"},"relationships":{"event":{"data":[{"type":"Assignment","id":"26"}]}}},{"type":"equipment","id":"3","attributes":{"name":"Infiniti iS-200","fabricator":"Showtec","storeplace":12,"labor":"","max_quantity":1,"status":"im Lager"},"relationships":{"event":{"data":[]}}},{"type":"equipment","id":"4","attributes":{"name":"HDL 20-A","fabricator":"RCF","storeplace":1,"labor":"","max_quantity":1,"status":"im Lager"},"relationships":{"event":{"data":[]}}},{"type":"equipment","id":"5","attributes":{"name":"HDL 20-SUB","fabricator":"RCF","storeplace":1,"labor":"","max_quantity":1,"status":"im Lager"},"relationships":{"event":{"data":[]}}},{"type":"equipment","id":"6","attributes":{"name":"F33 Taverse","fabricator":"Global Truss","storeplace":3,"labor":"","max_quantity":1,"status":"im Lager"},"relationships":{"event":{"data":[]}}},{"type":"equipment","id":"7","attributes":{"name":"Windup 80","fabricator":"Varytec","storeplace":3,"labor":"","max_quantity":1,"status":"im Lager"},"relationships":{"event":{"data":[]}}},{"type":"equipment","id":"8","attributes":{"name":"Flat PAR RBG","fabricator":"Stairville","storeplace":12,"labor":"","max_quantity":1,"status":"im Lager"},"relationships":{"event":{"data":[]}}},{"type":"equipment","id":"10","attributes":{"name":"mix 2000 usb","fabricator":"Behringer","storeplace":1,"labor":"","max_quantity":1,"status":"im Lager"},"relationships":{"event":{"data":[]}}},{"type":"equipment","id":"12","attributes":{"name":"TSX-12","fabricator":"JB-Systems","storeplace":1,"labor":"","max_quantity":1,"status":"im Lager"},"relationships":{"event":{"data":[]}}}],"meta":{"pagination":{"page":1,"pages":1,"count":10}}}方法签名应该类似于apply,但我不知道我正在尝试做的是否有正确的语法。

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

pull request 1775自己查看Odersky

  

让我们通过将最后一个参数部分移动到等号的右边来按摩(DB)(implicit RequestAction, ExecutionContext) => FieldProvider的定义:

f1
  

这个新版本f1的右侧现在是一个隐含的函数值   这个值的类型是什么?
  以前,它是def f1(x: Int) = { implicit thisTransaction: Transaction => thisTransaction.println(s"first step: $x") f2(x + 1) } ,也就是说,该函数具有隐式参数的知识在类型中丢失了。

     

pull请求实现的主扩展是引入隐式函数类型,这些函数类型反映了我们已经存在的隐式函数值   具体地说,新类型的f1是:

Transaction => Int
  

就像普通函数类型语法implicit Transaction => Int 一样,desugars到A => B,隐式函数类型语法scala.Function1[A, B]去了implicit A => B
  其他功能也是如此。合并dotty’s pull request #1758后,此类函数的上限不再为22。