Given some method
def f[A,B](p: A)(implicit a: X[A,B], b: Y[B])
Does the order of a
before b
within the implicit parameter list matter for type inference?
I thought only the placement of parameters within different parameter lists matters, e.g. type information flows only through parameter lists from left to right.
I'm asking because I noticed that changing the order of implicit parameters within the singly implicit list made a program of mine compile.
The following code is using:
Here is a simple sbt build file to help along with compiling the examples:
scalaVersion := "2.11.5"
libraryDependencies += "com.chuusai" %% "shapeless" % "2.1.0"
scalaSource in Compile := baseDirectory.value
Onto the example. This code compiles:
import shapeless._
import shapeless.ops.hlist.Comapped
class Foo {
trait NN
trait Node[X] extends NN
object Computation {
def foo[LN <: HList, N <: HList, TupN <: Product, FunDT]
(dependencies: TupN)
(computation: FunDT)
(implicit tupToHlist: Generic.Aux[TupN, LN], unwrap: Comapped.Aux[LN, Node, N]) = ???
// (implicit unwrap: Comapped.Aux[LN, Node, N], tupToHlist: Generic.Aux[TupN, LN]) = ???
val ni: Node[Int] = ???
val ns: Node[String] = ???
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
}
}
and this code fails
import shapeless._
import shapeless.ops.hlist.Comapped
class Foo {
trait NN
trait Node[X] extends NN
object Computation {
def foo[LN <: HList, N <: HList, TupN <: Product, FunDT]
(dependencies: TupN)
(computation: FunDT)
// (implicit tupToHlist: Generic.Aux[TupN, LN], unwrap: Comapped.Aux[LN, Node, N]) = ???
(implicit unwrap: Comapped.Aux[LN, Node, N], tupToHlist: Generic.Aux[TupN, LN]) = ???
val ni: Node[Int] = ???
val ns: Node[String] = ???
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
}
}
with the following compile error
Error:(22, 25) ambiguous implicit values:
both method hnilComapped in object Comapped of type [F[_]]=> shapeless.ops.hlist.Comapped.Aux[shapeless.HNil,F,shapeless.HNil]
and method hlistComapped in object Comapped of type [H, T <: shapeless.HList, F[_]](implicit mt: shapeless.ops.hlist.Comapped[T,F])shapeless.ops.hlist.Comapped.Aux[shapeless.::[F[H],T],F,shapeless.::[H,mt.Out]]
match expected type shapeless.ops.hlist.Comapped.Aux[LN,Foo.this.Node,N]
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
^
Error:(22, 25) could not find implicit value for parameter unwrap: shapeless.ops.hlist.Comapped.Aux[LN,Foo.this.Node,N]
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
^
Error:(22, 25) not enough arguments for method foo: (implicit unwrap: shapeless.ops.hlist.Comapped.Aux[LN,Foo.this.Node,N], implicit tupToHlist: shapeless.Generic.Aux[(Foo.this.Node[Int], Foo.this.Node[String]),LN])Nothing.
Unspecified value parameters unwrap, tupToHlist.
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
^
Normally it should not matter. If you look at the language spec it makes no mention about resolution being dependent on parameter order.
I looked at the source code of shapeless, and I could not come up with any reason why this error would present itself.
And doing a quick search through the bug repo of the language I found a similar issue that was apparently resolved. But it does not state if the fix involved treating the symptom (making context bounds not break compilation) or the cause (restrictions on implicit parameter ordering.)
Therefore I would argue that this is a compiler bug, and it is tightly related to the issue linked in point 3.
Also, I would suggest you submit a bug report if you can find a second opinion that resulted from a more rigorous analysis than my own :)
Hope this puts your mind at rest. Cheers!
According to my reading of the comments of the issue mentioned by Lorand Szakacs, I come to the conclusion that the order of implicit parameters matters in the current version 2.11
of the Scala compiler.
This is because the developers participating in the discussion appear to assume that the order matters; they do not state it explicitly.
I'm not aware of the language spec mentioning anything about this topic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With