0

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.

Krever
  • 1,371
  • 1
  • 13
  • 32

1 Answers1

1

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.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • So if I understand correctly, there is no way to hide implementation details of method operating on HList? If I would use 2x map, zip, fold, etc. all of them will leak out to the API(in form of type parameters and implicit evidences)? – Krever Nov 03 '16 at 06:11
  • At least, if there is such a way, I don't know it. – Alexey Romanov Nov 03 '16 at 06:34
  • There may be some solution of this problem with existential types, but haven't check if it works yet. – Krever Nov 05 '16 at 17:56