2016-04-17 13 views
6

In Scala für die Impatient Es wird gesagt, dassKovarianz und die Varianz Flip in scala

Funktionen sind kontravarianten in ihre Argumente und kovarianten in ihrem Ergebnistyp

Dies ist einfach und leicht zu verstehen, aber im selben Thema heißt es

Howev er innerhalb eines Funktionsparameter, die Varianz flips- seine Parameter covariant sind

und es dauert das Beispiel foldLeft Methode von Iterator als:

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

Ich bin nicht klar zu bekommen, was es sagt.

ich versucht, einige Blogs als

  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/

Aber nicht klares Verständnis bekommen haben.

Antwort

3

Eine Funktion in seinem Argumenttyp in der Regel kontra ist und kovariant in seiner Rückgabetyp eg

trait Function1[-T1, +R] extends AnyRef 

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

wo T1, T2, Tn ...... wo (n < = 22) sind Argumente und R ist der Rückgabetyp.

In der Funktion höherer Ordnung, in der eine Funktion einen Funktionswert annehmen kann, kann ein Argument den Typ Parameter haben, der in die Funktion z. foldLeft in Zug Iterable

Iterable deklariert als

trait Iterable[+A] extends AnyRef 

und foldLeft als

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

da eine ID als covariant erklärt, damit es als Rückgabetyp erscheinen sollte, aber Hier ist es in Argumenttyp aufgrund

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

weil op : (B, A) => B ist der Typ Function2.

Der Schlüssel dazu ist Merkmal Function2 in seinem Argument Typ kontra ist.

Daher Kovarianz-Typ wird in Verfahren Argumente erscheint aufgrund

trait Function2 in seinem Argumenttyp kontra ist

Das heißt Varianz Flip

  1. Flip der Kovarianz ist die Kontravarianz.
  2. Flip der Kontravarianz ist Kovarianz.
  3. Flip ist invariant ist invariant.

Deshalb invariant an einer beliebigen Position (Kovarianz/Kontra)

erscheinen
0

Es kommt darauf an, was es für eine Funktion bedeutet, ein Untertyp eines anderen zu sein. Es hört sich an, als ob Sie mit A- zufrieden sind.> B ist ein Subtyp von C-> D, wenn C der Subtyp von A (kontravariant im Eingabetyp) und B ein Subtyp von D (kovariant im Rückgabetyp) ist.

Betrachten Sie nun Funktionen, die andere Funktionen als Argumente annehmen. Betrachten Sie zum Beispiel (A-> B) -> B. Wir wenden das gleiche Argument zweimal an. Das Argument ist eine Funktion vom Typ A-> B und der Rückgabetyp ist B. Was muss wahr sein, um eine Funktion vom Typ C-> B als Eingabetyp zu liefern? Da Funktionen im Eingabetyp kontravariant sind, muss C-> B ein Subtyp von A-> B sein. Aber wie wir im ersten Absatz besprochen haben, bedeutet dies, dass A ein Subtyp von C sein muss. Nach zwei Anwendungen der Argumentation im ersten Absatz finden wir, dass (A-> B) -> B in der A-Position kovariant ist.

Sie können ähnlich mit komplizierteren Funktionen argumentieren. In der Tat sollten Sie sich davon überzeugen, dass eine Position kovariant ist, wenn sie links von einer geraden Anzahl von Pfeilen liegt, die für sie gelten.

0

Zunächst betrachten Sie eine Funktion als eine Klasse oder eher eine typeclass.Denken Sie über seine Art Function1[-A,+B] Sagen wir folgendes haben,

class x
class y extends b

Jetzt habe ich zwei Funktionen haben wie die folgende,

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

Nun, wenn ich eine andere Methode, wie die folgende haben,

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

Gemäß der Typensignatur Function1[-A,+B] kann ich test2 in acceptFunction sowie test1 wegen der contravariance übergeben. Art von wie test1<:test2.

Das ist eine ganz andere Sache, als zu sagen, dass Parameter zu einer Funktion kovariant sind. Das bedeutet, wenn Sie die folgende haben,

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

Sie die folgenden schreiben,

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

Aber Sie nicht schreiben können,

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