Why do I need to indicate the type of function's generic type parameter that should be inferred


I have the following example:

    trait MBase {
      type All
      def all: All

    case class aMBase() extends MBase {
      type All = (Double, Double)
      def all: All = (1,2)

    def map[T<:MBase](l: List[T], f: T => T#All) : List[T#All] = {

To use it I do:

    val ll = List(aMBase(), aMBase())
    def pp(b: aMBase) : b.All= b.all
    val rr: List[(Double, Double)] = map[aMBase](ll, pp)

However, the following fails:

    val rr: List[(Double, Double)] = map(ll, pp)

I get the error (scalac 2.12.2):

no type parameters for method map: (l: List[T], f: T => T#All)List[T#All] exist so that it can be applied to arguments (List[aMBase], aMBase => (Double, Double))
[error]  --- because ---
[error] argument expression's type is not compatible with formal parameter type;
[error]  found   : aMBase => (Double, Double)
[error]  required: ?0T => ?0T#All
[error]     val rr: List[(Double, Double)] = map(ll, pp)

Shouldn’t the compiler know that ?0T <: MBase and therefore bind 0T to aMBase?
If not, why?



There are probably a few ways to do this, but if you introduce a type parameter for the refinement Scala will be able to infer the return type.

def map[T <: MBase, A](l: List[T { type All = A }], f: T => A) : List[A] = {


val rr = map(ll, pp) // compiles


Ok, see the issue now. Seems this is the same issue that requires the use of the Aux pattern.

Thank you.