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

时间:2016-11-02 11:55:16

标签: scala shapeless

我想在无形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)

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

1 个答案:

答案 0 :(得分:1)

当您想要仅推断方法调用的某些类型参数时,通常的解决方案是将其拆分为2:第一个修复您感兴趣的参数并返回一个带有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类型推断的工作方式,它无法从IntermediateType推断出mapper1,然后在mapper2中使用它,所以我不确定它是否会正确找到mapper2。在将来的Scala版本中,这应该由def apply(implicit mapper1: ...)(implicit mapper2: ...)修复,但启用此wasn't accepted in time for 2.12.0的拉取请求。如果这是一个问题,那么您必须再次将ConvertTo.apply拆分为2。