2015-03-19 7 views
5

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) 
         ^
+0

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. –

+0

@ RégisJean-Gilles Ich habe ein kleines Beispiel hinzugefügt. – ziggystar

Antwort

1

Nach meiner Lektüre der von Lorand Szakacs erwähnten Kommentare von the issue komme ich zu dem Schluss, dass die Reihenfolge der impliziten Parameter in der aktuellen Version 2.11 des Scala-Compilers eine Rolle spielt.

Dies liegt daran, dass die Entwickler, die an der Diskussion teilnehmen, davon ausgehen, dass die Reihenfolge von Bedeutung ist; sie geben es nicht explizit an.

Ich bin nicht bewusst, dass die Sprachspezifikation irgendetwas zu diesem Thema erwähnt.

0

Neuanordnung wird sie nur Code brechen, die sie explizit gibt, sowie alle kompilierten Code. Alles andere wird unberührt bleiben.

+0

Bitte sehen Sie mein Beispiel. – ziggystar

2
  1. Normalerweise sollte es keine Rolle spielen. Wenn Sie sich die language spec ansehen, wird nicht erwähnt, dass die Auflösung von der Reihenfolge der Parameter abhängt.

  2. Ich schaute auf den Quellcode von formlos, und ich konnte keinen Grund finden, warum dieser Fehler sich darstellen würde.

  3. Und eine schnelle Suche durch den Bug Repo der Sprache fand ich eine similar issue, die anscheinend gelöst wurde. Aber es gibt nicht an, ob das Update das Symptom beteiligt Behandlung (machen Kontext Grenzen Kompilation nicht brechen) oder die Ursache (Beschränkungen impliziten Parameter Bestellung.)

Deshalb würde ich argumentieren, dass dies ein Compiler Fehler, und es ist fest mit dem 3.

auch in Punkt verknüpft Problem im Zusammenhang, würde ich vorschlagen, dass Sie einen Fehlerbericht einreichen, wenn Sie eine zweite Meinung finden kann, die von einer strengeren Analyse als meine eigene :)

Hoffnung resultierte Das beruhigt dich. Prost!

+2

Ich habe die Kommentare zu dem Problem gelesen, und es scheint, dass alle Kommentatoren implizit davon ausgehen, dass die Reihenfolge der impliziten Parameter zählt. – ziggystar

Verwandte Themen