einige VerfahrenIst die Reihenfolge der impliziten Parameter in Scala wichtig?
def f[A,B](p: A)(implicit a: X[A,B], b: Y[B])
Ist die Reihenfolge der a
vor b
innerhalb der impliziten Parameterliste Angelegenheit für Typinferenz gegeben?
Ich dachte nur die Platzierung von Parametern in verschiedenen Parameterlisten zählt, z. Typ Information fließt nur durch Parameterlisten von links nach rechts.
Ich frage, weil ich bemerkte, dass die Änderung der Reihenfolge der impliziten Parameter innerhalb der einfach impliziten Liste ein Programm von mir kompiliert.
Reales Beispiel
der folgende Code verwendet:
- formlos 2.1.0
- Scala 2.11.5
Hier ist eine einfache sbt-Build-Datei mit helfen entlang Zusammenstellen der Beispiele:
scalaVersion := "2.11.5"
libraryDependencies += "com.chuusai" %% "shapeless" % "2.1.0"
scalaSource in Compile := baseDirectory.value
Auf das Beispiel. Dieser Code kompiliert:
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)
}
}
und dieser Code nicht
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)
}
}
mit dem folgenden Compiler-Fehler
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)
^
Die Reihenfolge sollte nicht wichtig sein, zumindest für sich allein. Die Änderung der Reihenfolge des Impliziten ändert jedoch definitiv die Signatur der Methode, also ändert sie den Typ der Klasse/Eigenschaft, in der sie definiert ist. In jedem Fall sollten Sie auf jeden Fall ein Code-Snippet veröffentlichen, das zeigt, wie die Änderung der Reihenfolge das Kompilierungsergebnis ändert es ist schwer darüber zu diskutieren. –
@ RégisJean-Gilles Ich habe ein kleines Beispiel hinzugefügt. – ziggystar