2016-04-03 11 views
7

Sagen, ich habe eine einfache Klasse, wie dieseFolgern Art von generischen impliziten Parameter vom Rückgabetyp

abstract class Foo { 
    implicit val impInt: Int = 42 
    def f[A]()(implicit a: A): A 
    val f2: Int = f() 
} 

Wenn val erklärt f2, Compiler in der Lage ist zu folgern, dass die Art der impliziten Parameter der Funktion f ist Int, weil das type ist identisch mit dem Ergebnistyp, und der Ergebnistyp muss dem Werttyp f2 entsprechen, der Int lautet.

Allerdings wirft ein Ordering[A] in den Mix:

def f[A]()(implicit a: A, m: Ordering[A]): A 
val f2: Int = f() 

Ergebnisse in diesem Compiler-Fehler:

Ambiguous implicit values: both value StringCanBuildFrom in object Predef of type => scala.collection.generic.CanBuildFrom[String,Char,String] and method $conforms in object Predef of type [A]=> <:<[A,A] match expected type A

Wenn ich die Typinformationen hinzufügen, wenn f() Aufruf, es kompiliert:

val f2: Int = f[Int]() 

Zuerst stieß ich auf den Fall mit impliziter Reihenfolge ein d Ich dachte, es hat damit zu tun, dass Scala von links nach rechts schließt; Ich dachte, es ist nicht in der Lage, den Rückgabetyp zuerst und dann den (impliziten) Parametertyp von f abzuleiten. Aber dann habe ich den Fall ohne implizite Bestellung versucht und sah, dass es funktioniert - es gefolgert, dass f durch Int parametrisiert werden muss, weil der Rückgabetyp ein Int sein muss (weil f2 ist ein Int).

Beachten Sie, dass, wenn wir implicit a: A entfernen und nur die Reihenfolge impliziten Parameter verlassen, bleibt der Fehler, aber

Diverging implicit expansion for type Ordering[A] starting with method Tuple9 in object Ordering.

Wieder wird, geben Sie Parameter hinzufügen, so dass es val f2: Int = f[Int]() hilft wird.

Was ist los? Warum kann der Compiler folgern, dass der Parameter A ein Int sein muss, aber nicht dass der Parameter Ordering[A] ein Ordering[Int] sein muss?

Antwort

1

Die Art und Weise, wie Bestellungsinstanzen generiert werden, muss fehlerhaft sein, da der folgende Code funktioniert. Ich würde einen Fehler melden.

case object types { 
    implicit def buh[X]: List[X] = List() 
} 
abstract class Foo { 

    import types._ 

    def f[A]()(implicit l: List[A]): A 
    val f2: Int = f() 
} 
+1

Sieht aus wie [SI-8541] (https://issues.scala-lang.org/browse/SI-8541) –