2013-06-04 16 views
5

Próbuję uzyskać lepsze zrozumienie z następujących zachowań:typu Scala granice i wariancji

scala> class C[-A, +B <: A] 
<console>:7: error: contravariant type A occurs in covariant position 
        in type >: Nothing <: A of type B 
     class C[-A, +B <: A] 
        ^

Jednak następujące prace:

scala> class C[-A, +B <% A] 
defined class C 

widzę, że nie może być zagadnienia z wariancja zmiennych ograniczających i ograniczonych jest przeciwna, chociaż nie jestem pewien, jaki jest konkretny problem. Jeszcze mniej wiadomo, dlaczego zmiana typu związanego z widokiem powoduje, że wszystko jest w porządku. W przypadku braku odpowiednich niejawnych konwersji spodziewałbym się, że te dwie definicje będą miały w dużym stopniu ten sam skutek. Jeśli cokolwiek, spodziewałbym się, że widok zapewni więcej okazji do psot.

Dla nieco tło I definiowania klas, które są w pewnym sensie jak funkcje, a ja chciałem zrobić coś takiego

CompositeFunc[-A, +B <: C, -C, +D] (f1 : BaseFunc[A, B], f2 : BaseFunc[C, D]) 
    extends BaseFunc[A, D] 

zapewne

CompositeFunc[-A, +B <% C, -C, +D] (f1 : BaseFunc[A, B], f2 : BaseFunc[C, D]) 
    extends BaseFunc[A, D] 

jest rzeczywiście lepsze, ale nadal chciałbym lepiej zrozumieć, co się tutaj dzieje.

+0

Intrygujące ... Spędziłem 1 godzinę patrząc na przykład w przypadku typu przerwy bezpieczeństwa ze związanym typem. Nie znaleziono :( – gzm0

+0

Również jeśli był przykład, który był niesłuszny z powiązanym typem, trudno jest zobaczyć, jak zastąpiłby go widok w powiązaniu widoku. –

+0

Zgadzam się, ale podstawową różnicą jest to, że widok jest ograniczony. zawsze konwertuje zgodnie z typami, z którymi klasa została utworzona, ale niekoniecznie jest to związane z typem. (mówi przynajmniej moja intuicja ...) – gzm0

Odpowiedz

4

Najpierw łatwa:

class C[-A, +B <% A] 

Jest to odpowiednik

class C[-A, +B](implicit view: B => A) 

Od view nie jest publicznie wrócił, nie jest w pozycji, która będzie ograniczać wariancję A lub B. Na przykład.

class C[-A, +B](val view: B => A) // error: B in contravariant position in view 

Innymi słowy, C[-A, +B <% A] nie jest inaczej niż C[-A, +B] pod względem ograniczeń, widok argumentem niczego nie zmienia.


Górny oprawiony przypadek C[-A, +B <: A] Nie jestem pewien. Specyfikacja języka Scala w §4.5 stanowi

Położenie wariancji dolnej granicy typu deklaracji lub parametru typu jest przeciwieństwem pozycji wariancji deklaracji lub parametru typu.

Wariancja B nie wydaje się być zaangażowane, ale ogólnie górna granica musi być kowariantna:

trait C[-A, B <: A] // contravariant type A occurs in covariant position 

To musi jakoś produkować problem? Ale nie mogłem wymyślić przykładu, który dowodzi, że konstrukcja ta staje się nierzetelna w konkretnym przypadku ....


jak dla funkcji złożonej, dlaczego po prostu nie

class Composite[-A, B, +C](g: A => B, h: B => C) extends (A => C) { 
    def apply(a: A) = h(g(a)) 
} 

EDIT: Na przykład:

import collection.LinearSeq 

def compose[A](g: Traversable[A] => IndexedSeq[A], h: Traversable[A] => LinearSeq[A]) = 
    new Composite(g, h) 
+0

Ciekawe, dzięki. Nie pomyślałem o próbie "cechy C" [-A, B <: A] '. Po prostu pomyślałem, że musi to być odwrotna wariancja. –

+0

Tak, komponują, właśnie z powodu wariancji' Function1' –

+0

klasa 'CompositeFunc [-A, B, + C]' nie pozwoli ci skomponować 'f: BaseFunc (Traversable [A], IndexedSeq [A])' z 'g: BaseFunc (Traversable [A], LinearSeq [A])' chociaż ich kompozycje mają sens w obu zamówieniach. –