You need to try $ scalac -Ydebug -Yinfer-debug x.scala , but first you want to minimize it.
In this case, you will see how, in the version with curry, B is solved in the first parameter list:
[infer method] solving for B in (bs: B*)(bfs: Function1[B, _]*)Nothing based on (String)(bfs: Function1[B, _]*)Nothing (solved: B=String)
For the unladen version, you will see weirdness around
[infer view] <empty> with pt=String => Int
as it tries to eliminate the overload, which may lead you to a weird solution below.
The fictitious implicit serves the sole purpose of allowing overload so that a conclusion can be made. The implicit unused itself and remains unrealized ???
This is a rather strange decision, but you know that overloading is evil, right? And you must fight evil with any tools at your disposal.
Also see that a workaround for annotating a type is more time consuming than a regular parameter type in normal mode.
object Test extends App { def f[B](pairs: (B, B => _)*) = ??? def f2[B](bs: B*)(bfs: (B => _)*) = ??? def g(b: String) = ??? def g(b: Int) = ??? // explicitly f[String](Pair("hi", g _)) // solves for B in first ps f2("hi")(g _) // using Pair instead of arrow means less debug output //f(Pair("hi", g _)) locally { // unused, but selects g(String) and solves B=String import language.implicitConversions implicit def cnv1(v: String): Int = ??? f(Pair("hi", g _)) } // a more heavy-handed way to fix the type class P[A](a: A, fnc: A => _) class PS(a: String, fnc: String => _) extends P[String](a, fnc) def p[A](ps: P[A]*) = ??? p(new PS("hi", g _)) }