Se sei come me, di tanto in tanto vuoi scrivere metodi avanzati per le raccolte o le sequenze di Scala, ma desideri associare il tipo di raccolta e il tipo di elemento, non solo l'upcast a Seq [T].Come è possibile scrivere metodi di miglioramento Scala generici che associano il tipo di raccolta e il tipo di elemento?
6
A
risposta
7
C'è un modo per farlo, e funziona così:
object enhance {
import scala.language.higherKinds
import scala.language.implicitConversions
import scala.collection.SeqLike
import scala.collection.generic.CanBuildFrom
implicit class Enhance[T, S[E] <: SeqLike[E, S[E]]](seq: S[T]) {
def first3(implicit cbf: CanBuildFrom[S[T], T, S[T]]) = seq.take(3)
def foo = seq.iterator
def goo(implicit cbf: CanBuildFrom[Nothing, T, S[T]]) = foo.take(3).to[S]
def moo[U](f: T => U)(implicit cbf: CanBuildFrom[S[T], U, S[U]]) = seq.map(f)
}
}
Utilizzando il modello di firma tipo sopra, i metodi avanzati sono consapevoli sia del tipo di elemento T
(es Int
o String
) e il tipo di sequenza più alto tipo S
(ad esempio List
o Vector
) e quindi può restituire esattamente il tipo di sequenza su cui è stato chiamato.
Molti metodi di sequenza possono richiedere impliciti CanBuildFrom
, che vengono aggiunti ai metodi Enhance
come parametri impliciti, dove sono necessari negli esempi sopra.
A seguito di un esempio di esecuzione, che mostra i tipi di raccolta di ritorno superiore kinded desiderati:
scala> import enhance._
import enhance._
scala> (1 to 10).toList.first3
res0: List[Int] = List(1, 2, 3)
scala> (1 to 10).toVector.first3
res1: Vector[Int] = Vector(1, 2, 3)
scala> (1 to 10).toList.goo
res2: List[Int] = List(1, 2, 3)
scala> (1 to 10).toVector.goo
res3: Vector[Int] = Vector(1, 2, 3)
scala> (1 to 10).toList.moo(_.toDouble)
res4: List[Double] = List(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
scala> (1 to 10).toVector.moo(_.toDouble)
res5: Vector[Double] = Vector(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
Problemi correlati
- 1. metodi generici tipo di inferenza
- 2. È possibile scrivere un tipo di funzione dipendente in Scala?
- 3. Generics Java che estendono il tipo di metodi di restituzione
- 4. ritorno Tipo di Java metodi generici
- 5. Tipo Scala di tipo e tipo this.type in collezioni
- 6. Generici Swift che non conservano il tipo
- 7. tipo di controllo e generici
- 8. Restituisci il tipo di Scala per/yield
- 9. Come abbinare il tipo generico di scala?
- 10. proprietà di raccolta tipo
- 11. È sbagliato se il tipo di elemento contenitore standard e il tipo std :: allocator sono diversi?
- 12. Raccolta di tipi generici
- 13. Metodi generici C#, parametri di tipo nel vincolo costruttore new()
- 14. default Tipo di raccolta
- 15. Come invertire il tipo di raccolta di Groovy?
- 16. Scala: il parametro type di una raccolta sopravvive a "collect" quando il parametro type è un tipo di membro
- 17. generici Java, interfacce e vincoli di tipo
- 18. È possibile scrivere entità generiche di tipo in VHDL?
- 19. JS/jQuery - ottenere il tipo di elemento
- 20. Qual è il modo corretto in Python per scrivere metodi che richiedono solo un particolare tipo?
- 21. Come chiedere lo stesso tipo nei generici Scala senza introdurre un terzo parametro di tipo?
- 22. Tipo di trasmissione utilizzando il parametro tipo
- 23. È possibile eseguire un overloading dei metodi con generici e modificare solo il tipo generico della firma del metodo?
- 24. Ottieni il tipo di elemento selezionato
- 25. A proposito di farmaci generici Scala: impossibile trovare la classe manifesti per il tipo di elemento T
- 26. Qual è il tipo di oggetto nidificato in scala
- 27. Che tipo di casi di test possiamo scrivere usando DUnit?
- 28. Tipo per Traversable che esegue il mapping allo stesso tipo di Traversable
- 29. Tipo di differimento Scala
- 30. Che tipo di tipo Java è "[B"?
Inoltre è possibile definire classe come classe 'implicita Migliora [T, S [E] <: IterableLike [E, S [E]]] (seq: S [T]) {'e quindi non avrai bisogno di' asInstanceOf ' –
Non funzionerà, se usi' map' o qualsiasi altro metodo che prende un 'CanBuildFrom' nel nuovo metodo implementazioni. Il risultato sarebbe appena uscito come 'Seq'. Dovresti passare un "CanBuildFrom" implicito rilevante alla classe 'Enhance' o al metodo. – Kolmar
Grazie a @ НиколайМитропольский e Kolmar, entrambe queste modifiche sono molto utili! Ho rielaborato la mia risposta originale per mostrarli in azione. – eje