2015-08-25 11 views
7

Ecco un semplice riproduttore, in cui definisco un tipo di coppia "commutativa" che viene fornito con una conversione di riordino implicita. La conversione implicita viene applicata dal compilatore come previsto se l'argomento della funzione f si trova in un valore denominato preesistente (t nell'esempio). Tuttavia, se provo a chiamare f direttamente sul letterale CommutativePair, non riesce con un errore di tipo. In questo caso il compilatore non applica la conversione di riordino implicita.La conversione implicita di Scala si applica in alcune condizioni ma non in altre

object repro { 
    import scala.language.implicitConversions 

    case class CommutativePair[A, B](a: A, b: B) 

    object CommutativePair { 
    // Support a kind of commutative behavior via an implicit reordering 
    implicit def reorderPair[B, A](pair: CommutativePair[B, A]) = 
     CommutativePair(pair.b, pair.a) 
    } 

    // The idea is to allow a call to 'f' with Pair[Int, String] as well, 
    // via implicit reorder. 
    def f(p: CommutativePair[String, Int]) = p.toString 

    val t = CommutativePair(3, "c") 

    // This works: the implicit reordering is applied 
    val r1 = f(t) 

    // This fails to compile: the implicit reordering is ignored by the compiler 
    val r2 = f(CommutativePair(3, "c")) 
} 
+0

L'inferenza del tipo sembra fallire; quando aggiungi [Int, String] a CommutativePair ricompila. –

+0

@LodewijkBogaards, d'accordo, sto considerando di segnalarlo come un bug del compilatore di scala, ma in attesa di vedere che tipo di risposte ottengo. – eje

+0

Dovresti. Ho eseguito il codice in 2.11.7 e ho avuto lo stesso problema. Anche se posso immaginare che il compilatore abbia problemi con questo, dovrebbe funzionare. –

risposta

2

Credo che stia raggiungendo il limite dell'inferenza di scala, innescata dall'ordine in cui cerca le soluzioni. Nella prima situazione:

val t = CommutativePair(3, "c") 

La deduzione ha bloccato il tipo di CommutativePair[Int,String], perché è l'unico che potrebbe funzionare sulla base dei parametri. Così, quando si chiama:

val r1 = f(t) 

Si ottiene un tipo non corrispondente sul Commutative[Int,String] = = Commutative[String,Int], allora esso cerca impliciti e trova quello di cui sopra!.

Nel secondo caso, scala sta cercando di capire i tipi, facendo strada dall'esterno:

val r2 = f(CommutativePair(3, "c")) 
  • primo luogo, essa determina che f, deve prendere Commutative[String,Int].
  • Quindi, lo CommutativePair(...,...)deve essereCommutative[String,Int] (poiché non ha ancora capito che è il tipo dai suoi parametri).
  • Ora controlla i parametri su CommutativePair(...) e li trova di tipo errato. Ma questo non innescherà la conversione implicita perché pensa che la mancata corrispondenza sia nei parametri, non nel complesso CommutativePair(...).

In effetti, il blocco dei parametri di tipo (passando in modo esplicito o vincolando a un valore val per primo) corregge l'errore.

Problemi correlati