使用方法名称编写泛型函数

时间:2017-09-28 10:16:50

标签: scala generic-programming shapeless

我正在尝试编写以下方法:

case class Config2(repoName: String)

def buildAction[A, M, R <: HList]()
                          (implicit
                           gen: Generic.Aux[Config2, R],
                           mod: Modifier.Aux[R, M, A, A, R])
  : (A, Config2) => Config2 = {
    (arg: A, c: Config2) => {
      val rec = mod.apply(gen.to(c), _ => arg)
      gen.from(rec)
    }
  }

尝试使用时:

buildAction[String, Witness.`'repoName`.T, String :: HList]()

我收到错误:

could not find implicit value for parameter gen: shapeless.Generic.Aux[com.advancedtelematic.tuf.cli.Cli.Config2,shapeless.::[String,shapeless.HList]]
[error]   val _ = buildAction[String, Witness.`'repoName`.T, String :: HList]()
我在这里错过了一些导入吗?

第二个问题是,我可以以某种方式重写此签名,因此我不必指定所有类型吗?另外,Config2类型需要很长的字段列表,所以一直写这个字段并不实际

更新

我将其简化为以下内容:

  val CGen = LabelledGeneric[Config]

  def buildAction[A, M]()
                       (implicit mod: Modifier.Aux[CGen.Repr, M, A, A, CGen.Repr])
  : (A, Config) => Config = {
    (arg: A, c: Config) => {
      val rec = mod.apply(CGen.to(c), _ => arg)
      CGen.from(rec)
    }
  }

这让我只能写:

buildAction[String, Witness.`'repoName`.T]()

但我还是要指定Witness。这是我可以写buildAction[String]("repoName")并且有一些方法隐含地提供见证的方法吗?

更新:以下作品!

  val CGen = LabelledGeneric[Config]

  def buildAction[A](witness: Witness)
                    (implicit mod: Modifier.Aux[CGen.Repr, witness.T, A, A, CGen.Repr]):
  (A, Config) => Config = {
    (arg: A, c: Config) => {
      val rec = mod.apply(CGen.to(c), _ => arg)
      CGen.from(rec)
    }
  }

  buildAction[RepoName]('repoName)

1 个答案:

答案 0 :(得分:1)

  我在这里错过了一些导入吗?

不,可能只是String :: HList必须是String :: HNil

  

第二个问题是,我可以以某种方式重写此签名,以便我不必指定所有类型吗?

您可以使用称为kinda-curried type parameters的技巧:

object buildAction {
   class PartiallyApplied[A, M] {
      def apply[R <: HList]()(implicit ...)
   }
   def apply[A, M] = new PartiallyApplied[A, M]
}

用作

buildAction[String, Witness.`'foo`.T]()

此外,由于您的代码提到字段名称,您可能希望LabelledGenericops.record.Updater

结合使用