2016-04-17 17 views
6

In Scala per la Impaziente Si dice checovarianza e varianza vibrazione in scala

funzioni sono controindicati variante loro argomenti e covariante nel loro tipo di risultato

Questo semplice e facile da capire, tuttavia nello stesso argomento si dice

Howev er all'interno di un parametro di funzione, la varianza flips- i suoi parametri sono covarianti

e ci vuole l'esempio di foldLeft metodo Iterator come:

def foldLeft[B](z : B)(op : (B, A) => B) : B 

Non ricevo chiaramente quello che dice.

Ho provato alcuni dei blog come

  1. http://www.artima.com/pins1ed/type-parameterization.html

  2. http://blog.kamkor.me/Covariance-And-Contravariance-In-Scala/

  3. http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/

Ma non ha ottenuto chiara comprensione.

risposta

3

Una funzione è di solito contravariant nel suo tipo di argomento e covariante nel suo tipo di ritorno es

trait Function1[-T1, +R] extends AnyRef 

trait Function2[-T1, -T2, +R] extends AnyRef 

dove T1, T2, Tn ...... dove (n < = 22) sono argomenti e R è il tipo di ritorno.

In funzione ordine superiore in cui una funzione può assumere un valore di funzione un argomento può avere il parametro di tipo passato alla funzione ad es. foldLeft nel tratto Iterable

Iterable è dichiarato come

trait Iterable[+A] extends AnyRef 

e foldLeft è decalred come

def foldLeft[B](z : B)(op : (B, A) => B) : B 

poiché A id dichiarata come covariante quindi dovrebbe apparire come tipo di ritorno, ma Qui è in tipo argomento a causa di

trait Function2[-T1, -T2, +R] extends AnyRef 

perché op : (B, A) => B è di tipo litrale Function2.

La chiave di questo è tratto Function2 è contravariant nel suo tipo di argomento.

Quindi tipo di covarianza viene visualizzato nel metodo argomento causa

tratto Function2 è contravariant nel suo tipo di argomento

Questo è chiamato varianza vibrazione

  1. vibrazione di covarianza è controvarianza.
  2. La vibrazione della controvarianza è covarianza.
  3. Il flip invariante è invariante.

è per questo invariante possono apparire in qualsiasi posizione (covarianza/controvarianza)

0

Si riduce a ciò che significa per una funzione essere un sottotipo di un'altra. Sembra che tu stia bene con A-> B è un sottotipo di C-> D se C è sottotipo di A (controvariante nel tipo di input) e B è un sottotipo di D (covariante nel tipo di ritorno).

Considerate ora le funzioni che accettano altre funzioni come argomenti. Ad esempio, considerare (A-> B) -> B. Applichiamo lo stesso ragionamento due volte. L'argomento è una funzione di tipo A-> B e il tipo restituito è B. Cosa deve essere vero per fornire una funzione di tipo C-> B come tipo di input? Poiché le funzioni sono controvarianti nel tipo di input C-> B deve essere un sottotipo di A-> B. Ma come abbiamo discusso nel primo paragrafo, ciò significa che A deve essere un sottotipo di C. Quindi, dopo due applicazioni del ragionamento nel primo paragrafo, troviamo che (A-> B) -> B è covariante nella posizione A.

È possibile ragionare in modo simile con funzioni più complicate. In effetti, dovresti convincerti che una posizione è covariante se si trova a sinistra di un numero pari di frecce che si applicano ad essa.

0

Per iniziare, guardare una funzione come classe o piuttosto uno typeclass.Pensate a suo tipo Function1[-A,+B] Dire che abbiamo seguito,

class x
class y extends b

Ora ho due funzioni come il seguente,

val test1:x=>Int = //do something 
val test2:y=>int = //do something 

Ora, se ho un altro metodo come il seguente,

def acceptFunction(f: y => Unit, b: B) = //do something

Come per la firma del modello Function1[-A,+B] posso passare test2 a acceptFunction e test1 a causa dello contravariance. Un po 'come test1<:test2.

Questa è una cosa completamente diversa dal dire che i parametri di una funzione sono covarianti. Questo significa che se si dispone quanto segue,

class Fruit { def name: String="abstract" } 
class Orange extends Fruit { override def name = "Orange" } 
class Apple extends Fruit { override def name = "Apple" } 

è possibile scrivere quanto segue,

testM(new Apple()) 
def testM(fruit:Fruit)={} 

Ma non si può scrivere questo,

 testM(new Fruit()) 
    def testM(fruit:Apple)={} 
Problemi correlati