2012-02-04 14 views
8

Ho difficoltà a spiegare la differenza di comportamento tra valori impliciti aggiuntivi ricercati da un valore implicito primario o una conversione implicita . In particolare, questo funziona:Perché Scala non riesce a trovare un valore implicito secondario in questo caso particolare?

trait Foo[A] 
implicit def fooString: Foo[String] = null 

implicit def value[A](implicit foo: Foo[A]) = 5 

> implicitly[Int] 
5 

Ma questo non lo fa:

implicit def conversion[A](x: Int)(implicit foo: Foo[A]) = new { 
    def aMethod = 5 
} 

> 1.aMethod 
could not find implicit value for parameter foo: test.Foo[A] 

Variante:

  • Se la ricerca viene avviata implicitly o una conversione implicita
  • Sia l'implicito secondaria valore ricercato è polimorfo
  • Se il valore implicito secondario fornito è polimorfico

ottengo i seguenti risultati:

Conversion/value Searching for Supplied | Works? 
---------------- ------------- -------- | ------ 
    conversion  poly   poly | yes 
    conversion  poly   mono | **no** 
    conversion  mono   poly | yes 
    conversion  mono   mono | yes 
    value   poly   poly | yes 
    value   poly   mono | yes 
    value   mono   poly | yes 
    value   mono   mono | yes 

Come si può vedere, l'unico caso che non funziona è quando la ricerca viene avviata da una conversione implicita, il valore cercato è polimorfico, tuttavia il valore fornito è monomorfico.

Esiste un motivo teorico per cui questo dovrebbe essere il caso, oppure si tratta di un bug/limitazione di Scala?

risposta

7

Sei stato morso dal bug scalac SI-3346. Più in generale vedi la descrizione di SI-4699, esp. punto (1),

1) Ricerca implicita e ricerca conversione implicita trattano i parametri di tipo diverso indeterminati

che si sta osservando direttamente dove i casi sono distinguendo tra valori impliciti e le conversioni implicite.

Ho aggiornato SI-3346 per includere questo come un ulteriore esempio.

3

Modifica la firma della conversione implicita seguente modo:

implicit def conversion[A](a: A)(implicit foo: Foo[A]) = new { 

quindi chiamare aMethod su un valore di tipo per il quale è definito un valore implicito, cioè con un stringa:

scala> "foo".aMethod 
res0: Int = 5 
+1

Risposta giusta, domanda sbagliata ;-) –

Problemi correlati