在函数签名中省略中间类型

Omit intermediate types in function signature

我想在无形 HList 上执行两个映射,我有以下有效的代码:

object doubleToInt extends Poly1 {
  implicit def caseDouble = at[Double](_.toInt)
}


object intToDouble extends Poly1 {
  implicit def caseInt = at[Int](_.toDouble)
}

def convert[InputType<:HList, ResultType<:HList, IntermediateType<:HList](input: InputType)(
  implicit mapper1: Mapper.Aux[doubleToInt.type , InputType, IntermediateType],
  mapper2: Mapper.Aux[intToDouble.type, IntermediateType, ResultType]
): ResultType = {
  input.map(doubleToInt).map(intToDouble)
}

convert(2.5 :: HNil)

正如我们所见,convert 的类型包含一个类型参数 IntermediateType,它与此函数的调用者完全无关。是否可以以某种方式隐藏它?这是个问题,因为我想这样调用:

convert[SomeType, SomeType2, _](2.5 :: HNil)

但由于未绑定类型参数,它无法编译。

当您只想推断方法调用的某些类型参数时,正常的解决方案是将其分成 2 个:第一个修复您感兴趣的参数,returns 一个带有 apply 的助手被调用以推断其余部分的方法。在这里应用它,你会得到

def convert[ResultType <: HList] = new ConvertTo[ResultType]

class ConvertTo[ResultType <: HList] {
  def apply[InputType <: HList, IntermediateType <: HList](input: InputType)(implicit mapper1: Mapper.Aux[doubleToInt.type, InputType, IntermediateType],
  mapper2: Mapper.Aux[intToDouble.type, IntermediateType, ResultType]
) = input.map(doubleToInt).map(intToDouble)
}

用法:convertTo[SomeType].apply(2.5 :: HNil)InputType 是从 input 推断出来的,然后编译器找到隐含的 mapper1 并推断出 IntermediateType.

或者至少,理想情况下它会:由于 Scala 类型推断的工作方式,它不能从 mapper1 推断 IntermediateType 然后在 mapper2 中使用它,所以我不确定它是否会正确找到 mapper2。在未来的 Scala 版本中,这应该由 def apply(implicit mapper1: ...)(implicit mapper2: ...) 修复,但是启用此 wasn't accepted in time for 2.12.0 的拉取请求。如果这证明是个问题,您将不得不再次将 ConvertTo.apply 分成 2 个。