I would like to perfom two maps over shapeless HList, I have folllowing code that works:
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)
as we can see the type of convert
contains a type parameter IntermediateType
that is completely irrelevant to the caller of this function. Is it posible to hide it somehow? It's a problem because I would like to call like this:
convert[SomeType, SomeType2, _](2.5 :: HNil)
but it doesn't compile because of unbound type parameter.
The normal solution when you want to infer only some type parameters of a method call is to split it into 2: the first fixes parameters you are interested in and returns a helper with apply
method which is called to infer the rest. Applying this here, you'd get
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)
}
Usage: convertTo[SomeType].apply(2.5 :: HNil)
. InputType
is inferred from input
and then the compiler finds the implicit mapper1
and infers IntermediateType
.
Or at least, ideally it would: due to the way Scala type inference works, it can't infer IntermediateType
from mapper1
and then use it in mapper2
, so I am not sure it'll find mapper2
correctly. In future Scala versions this should be fixed by def apply(implicit mapper1: ...)(implicit mapper2: ...)
, but the pull request enabling this wasn't accepted in time for 2.12.0. If this turns out to be a problem, you'll have to split ConvertTo.apply
in 2 again.