2012-06-27 19 views
5

Zwykle podczas zbierania wszystkich elementów sekwencji pasujących do określonego typu kolekcja wynikowa ma zarówno typ oryginalna kolekcja i typ wybrany dla:Scala: Czy parametr type kolekcji przetrwa "zbieranie", gdy parametr type jest typem członka

trait Foo 
trait Bar 

trait Baz { 
    // Works 
    def def1(foo: Seq[Foo]): Seq[Foo with Bar] = 
    foo collect {case foobar: Bar => foobar} 
} 

ta działa nawet wtedy, gdy typ wejście jest parametryzowane przez ograniczonego typu członkowskim i wszystkim chcę z powrotem jest sekwencją parametryzowane przez typ oprawionego (nie typu member):

trait Baz { 
    type memberType <: Foo 

    // Works 
    def2(foo: Seq[memberType]): Seq[Foo with Bar] = 
    foo collect {case foobar: Bar => foobar} 
} 

Jednak ten fai ls gdy faktycznie chcę z powrotem sekwencję sparametryzować przez typ członkiem: Komunikat

trait Baz { 
    type memberType <: Foo 

    // Fails 
    def def3(foo: Seq[memberType]): Seq[memberType with Bar] = 
    foo collect {case foobar: Bar => foobar} 
} 

Błąd:

error: type mismatch; 
found : Seq[this.Foo with this.Bar] 
required: Seq[Baz.this.memberType with this.Bar] 
    foo collect {case foobar: Bar => foobar} 

Aby odzyskać funkcjonalność, mogę to typ użytkownika w wywołaniu collect, ale to wydaje się zbędny biorąc pod uwagę, że każdy element musi pasować do tego typu z powodu podpisu:

trait Baz { 
    type memberType <: Foo 

    // Works 
    def def4(foo: Seq[memberType]): Seq[memberType with Bar] = 
    foo collect {case foobar: memberType with Bar => foobar} 
} 

Czy istnieje sposób zdefiniowania sekwencji typów elementów, aby pamiętały typy ich członków, gdy wydano collect?

+1

Czy sprawdziłeś kod pod kątem ostrzeżeń? Ponieważ 'memberType' jest abstrakcyjne, jest usuwane w teście' foobar: memberType with Bar'. –

+0

Jestem lekko zdezorientowany, dlaczego 1 i 2 działają nawet. Zebrana sekwencja to po prostu Seq [Bar], ale kompilator nadal pozwala na wpisanie jej jako Seq [Foo with Bar]. Okej, chyba jestem bardziej zdezorientowany, dlaczego nie spowoduje to ostrzeżenia o wymazaniu. – Kaito

+0

Nie widzę ostrzeżeń po uruchomieniu żadnego z działających przykładów. Czy wpis wymazania ma jakikolwiek wpływ na ostatni przykład (który został zmodyfikowany w celu poprawnego wskazania, że ​​"działa")? – drhagen

Odpowiedz

1

To nie jest odpowiedź, ale tylko spostrzeżenie. To działa:

trait Baz[A <: Foo] { 
    def def3(foo: Seq[A]): Seq[A] = 
    foo collect {case foobar => foobar} 
} 

ale to nie:

trait Baz[A <: Foo] { 
    def def3(foo: Seq[A]): Seq[A] = 
    foo collect {case foobar: Bar => foobar} 
} 

też nie:

trait Baz[A] { 
    def def3(foo: Seq[A]): Seq[A] = 
    foo collect {case foobar: Bar => foobar} 
} 

więc wydaje się być efektem dopasowującego wzór; Myślę, że nie ma to nic wspólnego z collect w szczególności. Jakoś to traci informacje, gdy tylko dodasz typ do przypadku meczu: -/

Ale jako Kaito, byłem naprawdę zaskoczony, że twoje pierwsze dwa przypadki wykonały. Musi to być (i wydaje się rozsądne), że algorytm wnioskowania typu odróżnia znany znany typ stabilny (Foo) od parametru lub elementu typu. Być może będziesz musiał poprosić o listę dyskusyjną języka scala, aby uzyskać od guru kompilatora odpowiedź na pytanie ...