使用方法名编写泛型函数

writing generic function using method name

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

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") 并让一些方法隐式提供 Witness 吗?

更新:以下作品!

  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)

am I missing some import here?

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

Second question is, can I somehow rewrite this signature so I don't don't have to specify all the types?

你可以使用一个技巧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

结合使用