2011-01-05 19 views
6

I tre sottotipi immediati di Iterable sono Map, Seq e Set. Sembra che, a parte i problemi di prestazioni, uno Seq sia una mappa da numeri interi a valori e uno Set sia una mappa da valori a valori booleani (true se il valore è nell'insieme, false altrimenti).Perché Seq [V] non estende Map [Int, V] né Set [V] estende Map [V, Bool]?

Se questo è il caso, perché questo non è espresso nel sistema di tipo facendo Seq[V] estendono Map[Int, V] e Set[V] estendono Map[V, Boolean]?

+0

'Set' e' Seq' hanno una semantica molto diversa da 'Mappa', quindi non avrebbe senso esporli in questo modo. – Gabe

+0

@Gabe, potresti fornire un esempio specifico di cosa intendi per "semantica diversa"? – Adam

+1

Penso che questa sia una domanda interessante, ma la risposta di Madoc è dispositive. – Malvolio

risposta

12

Beh, in qualche modo funzionano, almeno in realtà funzionalità comuni. Seq[B] eredita da Int => B (via PartialFunction[Int, B]), Map[A, B] eredita da A => B (anche tramite PartialFunction[A, B]) e Set[A] eredita da A => Boolean. Pertanto, per quanto riguarda i metodi di applicazione e composizione della funzione, tutti e tre possono essere usati in modo intercambiabile. Inoltre, possono essere utilizzati in modo intercambiabile per tutto il percorso, poiché tutti implementano TraversableLike.

+0

Grazie! In tal caso, suppongo che la mia domanda cambi un po ': qual è la differenza fondamentale di 30 parole o meno tra una mappa [A, B] e la funzione [A, B]? – Adam

+1

@Adam Una 'Mappa' è percorribile, mentre una' Funzione' no. Quindi una 'Mappa' può enumerare le sue chiavi, ma una' Funzione' non può fare lo stesso per i suoi parametri. –

4

Beh, se tutto si preoccupano Seq e Set era che, si avrebbe un punto. A mio parere, penso che sia uno degli aspetti meno importanti, e uno che è già ben rappresentato da tutte le funzioni .

Cioè, un Map è una funzione di una chiave in un valore, un Seq è una funzione di un Int in un valore, e un Set è una funzione di un valore in un Boolean. Questa proprietà, che hai chiamato una "mappa", è una funzione. Ed è già condiviso da tutti e tre.

Quali sono, a mio parere, Map, Seq e Set sono veramente sono:

  • Un Seq è preoccupato di sapere in quale ordine i suoi elementi sono. Concettualmente, come anteporesti un elemento a Map? Dovresti rinumerare tutte le chiavi!

  • A Set è preoccupato per la presenza o l'assenza di un elemento. Come si modellerebbe quello in un Map? Dovrebbe essere una mappa con valore predefinito - non una mappa comune - e una in cui tutti i valori non predefiniti sono gli stessi! Questo è chiaramente un comportamento degenerato, non un'astrazione.

  • A Map si preoccupa di associare chiavi arbitrarie a valori arbitrari. Un Seq non ha chiavi arbitrarie e un Set non ha valori arbitrari.

+0

"Beh, se tutto quello che ti interessa" - beh, la mia domanda potrebbe essere riformulata come "cosa, in particolare, è che i designer della biblioteca Scala si preoccupano di ciò che li ha portati a prendere questa decisione"? – Adam

+0

@Adam Vedi http://www.scala-lang.org/sid/3, http://www.scala-lang.org/docu/files/collections-api/collections.html e http: // www. scala-lang.org/docu/files/collections-api/collections-impl.html. –

8

Vedere una sequenza come un compito da interi a elementi è solo un modo per descrivere cos'è una sequenza. Ci sono altri modi, e non c'è motivo per cui quel modo di descrivere una sequenza debba diventare canonico. Lo scopo reale di una sequenza è quello di rendere un gruppo di elementi accessibili e attraversabili. Non è richiesta una sequenza per assegnare effettivamente numeri interi agli elementi. Ad esempio, la maggior parte delle implementazioni di Stream probabilmente non ha un contatore in esecuzione in parallelo al traversal. Richiedere ciò imporrebbe un inutile sovraccarico all'implementazione.

Inoltre, uno Map[K,V] è anche un Iterable[(K,V)]. Seguendo il tuo suggerimento, un Seq[A] dovrebbe anche essere un Map[Int,A], che sarebbe anche un Iterable[(Int,A)]. Poiché Seq estende Iterable, questo renderebbe il Seq[A] sia un Iterable[A] ed un Iterable[(Int,A)] (e, ricorsivamente, un Iterable[(Int,(Int,A))], Iterable[(Int,(Int,(Int,A)))], e così via), che non è un modo permesso di ereditarietà in Scala.

È possibile creare un argomento simile per il suggerimento relativo a Set.

+2

Penso che il secondo argomento sia convincente. Per semplificarlo, se 'Seq [A]' estendesse 'Map [Int, A]', cosa restituirebbe 'seq.elements()'? – Malvolio

+0

Interessante. Il sistema di tipo di Haskell soffre di tale limitazione (in effetti, ostenta questo tipo di polimorfismo a destra ea sinistra). Interessante vedere come la teoria sottostante di Scala abbia limitato la sua libreria standard. – Adam

+1

@Adam Non vedo neanche Haskell uscire da quello. Se si 'foldr' come lista in Haskell, non si piega tuple' (Int, A) ': si piega' A'. –