Diciamo che ho un tratto marcatore vuoto denominato Marker
e alcune funzioni con parametri di tipo legati da Marker
:Perché questa funzione di Scala viene compilata quando l'argomento non è conforme al vincolo di tipo?
trait Marker
object Marker {
def works[M <: Marker](m:M):M = m
def doesntWork[M <: Marker](f:M => String):String = "doesn't matter"
}
La prima funzione funziona come mi aspetto. Cioè, se si passa un parametro che non è un Marker
, quindi il codice non compila:
scala> works("a string")
<console>:14: error: inferred type arguments [String] do not conform to method works's type parameter bounds [M <: com.joescii.Marker]
works("a string")
^
<console>:14: error: type mismatch;
found : String("a string")
required: M
works("a string")
^
Tuttavia, sono in grado di passare un parametro per la seconda funzione che non è conforme alla Marker
. In particolare, posso passare una funzione di tipo String => String
e il codice compila felicemente e corre:
scala> doesntWork((str:String) => "a string")
res1: String = doesn't matter
mi si aspetterebbe questa chiamata a doesntWork
a fallire per la compilazione. Qualcuno può spiegarmi perché compila e come posso modificare la firma della funzione per evitare che i tipi controllino in questi casi?
Informazioni complete: l'esempio sopraindicato è una versione semplificata di this outstanding issue for lift-ng.
Ma l'OP sta passando '(str: String) =>" una stringa "' come argomento - questo non è di tipo 'Any => String' (né alcun sottotipo di esso)? – chi
è sbagliato, verifica la risposta di @larsrh – kosii
Questo è comunque utile. Non stavo pensando al fatto che 'M => String' è in realtà' Function1 [M, String] 'che potrebbe aver messo in moto la mia bandiera mentale per considerare la contravarianza. Conosco il concetto, ma sicuramente non lo so _know_ it. :) – joescii