2013-05-11 16 views
7

Avevo il sospetto che ci sarebbe stato un supporto per questo già incorporato nel sistema di tipi di Scala, ma dopo aver superato Numeric e Fractional e FractionalProxy, non ero in grado di capire un modo.Riassunto su Float, Double e BigDecimal in Scala

Voglio definire un modello numerico in modo astratto, in modo che possa funzionare con Doubles, Floats e BigDecimals, con specializzazioni per Float e Double.

Mi sembra di averlo fatto funzionare, ma con un sacco di sforzi e standard. Innanzitutto, c'è (per favore?) Un modo meno sfacciato e più conciso? In secondo luogo, il mio utilizzo di tipi di valore sarà efficace nel mantenere i tipi specializzati-primitivi di essere impacchettati, nonostante le implicite conversioni dei limiti di vista?

Molte grazie.

object Model { 

    sealed trait Value[T] extends Any { //contains all the operations I use 
    def value : T; 
    def + (other : Value[T]) : Value[T]; 
    def/(other : Value[T]) : Value[T]; 
    def - (other : Value[T]) : Value[T]; 
    def * (other : Value[T]) : Value[T]; 
    def < (other : Value[T]) : Boolean; 

    def unary_- : Value[T]; 
    def abs : Value[T]; 
    } 

    implicit def unwrap[T](wrapped : Value[T]) : T = wrapped.value; 

    implicit class FloatValue(val value : Float) extends AnyVal with Value[Float] { 
    def + (other : Value[Float]) : Value[Float] = new FloatValue(value + other.value) 
    def/(other : Value[Float]) : Value[Float] = new FloatValue(value/other.value) 
    def - (other : Value[Float]) : Value[Float] = new FloatValue(value - other.value) 
    def * (other : Value[Float]) : Value[Float] = new FloatValue(value * other.value) 
    def < (other : Value[Float]) : Boolean = value < other.value; 

    def unary_- : Value[Float] = new FloatValue(-value); 
    def abs : Value[Float] = new FloatValue(math.abs(value)); 
    } 

    implicit class DoubleValue(val value : Double) extends AnyVal with Value[Double] { 
    // body of FloatValue repeated, but with Double replacing Float 
    } 

    implicit class BigDecimalValue(val value : BigDecimal) extends AnyVal with Value[BigDecimal] { 
    // body of FloatValue repeated, but with BigDecimal replacing Float 
    } 
} 

class GrossInterestModel[@specialized(Double,Float) T <% Value[T]](zero : T) { 
    def runModel(a : T, b : T) : T = { 
     //do math here, using the operations defined in Value above 
    } 
} 
+2

Si potrebbe desiderare di avere uno sguardo a https://github.com/non/spire e vedere se si adatta al vostro caso d'uso. – huynhjl

+0

wow, grazie. la guglia sembra incredibile. –

+0

@huynhjl Forse dovresti copiare il tuo commento come risposta. Sarei felice di revocarlo - Spire sembra molto interessante. –

risposta

2

La raccolta integrata Scala è già stata implementata in modo simile in Numeric.scala. Puoi usarli direttamente. Qualche cosa come (da TraversableOnce.scala):

def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus) 
+0

sì, ho vagato attraverso queste astrazioni, ma in un certo senso in modo bizzarro, operazioni ordinarie come/non sono definite su di esse. –