2012-06-27 13 views
5

Normalmente, quando raccolgono tutti gli elementi di una sequenza che corrispondono a un particolare tipo, la raccolta risultante ha sia il tipo di collezione originale e il tipo selezionato per:Scala: il parametro type di una raccolta sopravvive a "collect" quando il parametro type è un tipo di membro

trait Foo 
trait Bar 

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

funziona Ciò anche quando il tipo l'ingresso è parametrizzato da un tipo di elemento limitato e tutto quello che voglio indietro è una sequenza parametrizzato in base al tipo legato (non il tipo membro):

trait Baz { 
    type memberType <: Foo 

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

Tuttavia, questo fai ls quando ho voglia di nuovo una sequenza parametrizzato in base al tipo membro: messaggio

trait Baz { 
    type memberType <: Foo 

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

Errore:

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

di recupero della funzionalità, che possono includere il tipo di membro nella chiamata collect, ma che sembra ridondante dato che ogni elemento deve corrispondere quel tipo a causa della firma:

trait Baz { 
    type memberType <: Foo 

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

c'è un modo per definire una serie di tipi di membri in modo che si ricordano il loro tipo di membro quando collect ed?

+1

Hai controllato quel codice per gli avvisi? Poiché 'memberType' è astratto, viene cancellato nel controllo' foobar: memberType con Bar'. –

+0

Sono un po 'confuso perché anche 1 e 2 funzionano. La sequenza raccolta è solo una Seq [Bar], ma il compilatore consente comunque di essere digitato come Seq [Foo con Bar]. Ok, credo di essere più confuso perché questo non si traduce in un avviso di cancellazione. – Kaito

+0

Non vedo alcun avviso quando eseguo uno degli esempi di lavoro. La cancellazione di tipo avrebbe avuto qualche effetto sull'ultimo esempio (che è stato modificato per indicare correttamente che "Funziona")? – drhagen

risposta

1

Questa non è una risposta, ma solo qualche osservazione. Questo funziona:

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

ma questo non:

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

anche questo non:

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

quindi sembra essere un effetto del matcher modello; Non penso che abbia nulla a che fare con collect in particolare. In qualche modo perde informazioni non appena si aggiunge il tipo al caso partita: -/

Ma, come Kaito, sono stato davvero sorpreso, anche, che i primi due casi fatto lavoro. Deve essere (e sembra ragionevole) che l'algoritmo di inferenza del tipo faccia la differenza tra un tipo stabile noto (Foo) e un parametro di tipo o un membro del tipo. Potrebbe essere necessario chiedere sulla mailing list scala lingua per ottenere alcuni dei guru del compilatore per rispondere alla domanda ...