In Scala, mi piacerebbe essere in grado di scrivere classi generiche che usano operatori come>, /, * ecc, ma non vedo come vincolare T in modo che funzioni.Scala: Qual è il modo migliore per eseguire operazioni numeriche in classi generiche?
Ho cercato T vincolato con Ordinato [T], ma non sembra funzionare poiché solo RichXXX (ad esempio RichInt) lo estende, non Int ecc. Ho visto anche Numeric [T], è disponibile solo in Scala 2.8?
Ecco un esempio specifico:
class MaxOfList[T](list: List[T]) {
def max = {
val seed: Option[T] = None
list
.map(t => Some(t))
// Get the max
.foldLeft(seed)((i,m) => getMax(i,m))
}
private def getMax(x: Option[T], y: Option[T]) = {
if (x.isDefined && y.isDefined)
if (x > y) x else y
else if (x.isDefined)
x
else
y
}
}
Questa classe non compilerà, perché ci sono molti Ts che non supportano> ecc
Pensieri?
Per ora ho usato un tratto MixIn per aggirare il problema:
/** Defines a trait that can get the max of two generic values
*/
trait MaxFunction[T] {
def getMax(x:T, y:T): T
}
/** An implementation of MaxFunction for Int
*/
trait IntMaxFunction extends MaxFunction[Int] {
def getMax(x: Int, y: Int) = x.max(y)
}
/** An implementation of MaxFunction for Double
*/
trait DoubleMaxFunction extends MaxFunction[Double] {
def getMax(x: Double, y: Double) = x.max(y)
}
Che se alteriamo la classe originale può essere miscelato in al momento dell'istanza.
P.S. Mitch, ispirato dal ri-scrittura di getMax, qui è un altro:
private def getMax(xOption: Option[T], yOption: Option[T]): Option[T] = (xOption,yOption) match {
case (Some(x),Some(y)) => if (x > y) xOption else yOption
case (Some(x), _) => xOption
case _ => yOption
}
Grazie ancora Mitch. Giuro che ci ho provato e non ho potuto farlo compilare! –
Ho aggiunto un aggiornamento alla domanda originale con un'altra versione di getMax ispirata alla tua. –
Ho aggiornato il mio getMax con un'altra versione ispirata alla tua. Quante altre iterazioni prima di raggiungere una sorta di singolarità? –