2017-08-08 2 views
0

dieses einfache Beispiel betrachten:Covariant Typ FParam tritt in kontra Position in Art Seq [FParam] Wert errät

trait Optimizer[+FParam, FRes] { 
    def optimize(
    fn: (FParam) => FRes, 
    guesses: Seq[FParam] // <--- error 
) 
} 

Es kompiliert nicht, weil

Covariant Typ FParam in kontra auftritt Position im Typ Seq[FParam] von Wertschätzungen.

Aber seq ist definiert als trait Seq[+A], also was ist die Quelle dieser Kontravarianz? (Frage 1)

Umgekehrt betrachten dieses einfache Beispiel mit -FParam:

trait Optimizer[-FParam, FRes] { 
    def optimize(
    fn: (FParam) => FRes, // <--- error 
    guesses: Seq[FParam] 
) 
} 

kontra Typ tritt in kovarianten Position in Art (FParam) => FRes

Auch hier das gleiche paradox: in Function1[-T1, R], der erste Typparameter ist eindeutig kontravariant, also warum ist FParam in einer kovarianten Position? (Question2)

Ich kann dieses Problem beheben, indem Sie die Varianz wie in Lower type bounds beschrieben spiegeln, aber warum es notwendig ist, ist unklar.

trait Optimizer[+FParam, FRes] { 
    type U <: FParam 

    def optimize(
    fn: (FParam) => FRes, 
    guesses: Seq[U] 
) 
} 

Antwort

0

Das Problem ist, dass FParam nicht direkt verwendet wird. Es ist in dem Argument von optimize, und als solches wird seine Varianz umgedreht. Zur Verdeutlichung schauen wir uns auf die Art der optimize (siehe val optim):

trait Optimizer[+FParam, FRes] { 
    type U <: FParam 

    def optimize(
    fn: (FParam) => FRes, 
    guesses: Seq[U] 
) 

    val optim: Function2[ 
    Function1[ 
     FParam, 
     FRes 
    ], 
    Seq[U], 
    Unit 
    ] = optimize 
} 
2

Frage 1: +FParam bedeutet die covariant Typ FParam und es variiert von geordneter TypFParam Subtyp. für die guesses erwartet es cotravariant type für Seq. So können Sie es tun, indem Sie explizit eine supertype von FPParam für diese Angabe, wie:

def optimize[B >: FParam](fn: (B) => FRes, guesses: Seq[B]) // B is the super type of FParam 

oder wie die SeqViewLike.

so für warum guesses es erwartet cotravariant type für Seq? zum Beispiel:

trait Animal 

case class Dog() extends Animal 

case class Cat() extends Animal 
val o = new Optimizer2[Dog, Any] 
val f: Dog => Any = (d: Dog) => ... 
o.optimize(f, List(Dog(), Cat())) // if we don't bind B in `guesses` for supertype of `FParam`, it will fail in compile time, since the `guesses` it's expecting a `Dog` type, not the `Animal` type. when we bind it to the supertype of `Dog`, the compiler will infer it to `Animal` type, so `cotravariant type` for `Animal`, the `Cat` type is also matched. 

Frage 2: -FParam bedeutet den cotravairant Typen FParam und es ist von übergeordnetem Typ FParam es Subtyp .für fn: Function1[-T1, +R]//(FParam) => FRes ist, ist es covariant Typen dafür zu erwarten.So können Sie es durch die umgekehrte Frage 1 Art Zustand, wie:

def optimize[B <: FParam](fn: (B) => FRes, guesses: Seq[B]) // B is the sub type of FParam 
tun