2013-05-11 58 views
7

我懷疑是否已經支持Scala的類型系統,但是在涉及Numeric和Fractional和FractionalProxy之後,我無法找到一種方法。在Scala中浮點,雙精度和BigDecimal的抽象

我想要抽象地定義一個數字模型,以便它可以與Double,Floats和BigDecimals一起使用,並具有Float和Double的專門化。

我似乎已經使它工作,但有很多努力和樣板。首先,有沒有(請?)少一點kludgey,更簡潔的方式?其次,儘管視圖邊界的隱式轉換,我使用值類型是否能有效地防止專用原始類型被封裝?

非常感謝。

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

您可能想看看https://github.com/non/spire並查看它是否適合您的用例。 – huynhjl 2013-05-11 21:11:43

+0

哇,謝謝。尖塔看起來有點神奇。 – 2013-05-11 22:17:47

+0

@huynhjl也許你應該複製你的評論作爲答案。我很樂意加入它 - Spire看起來非常有趣。 – 2013-05-22 19:25:05

回答

2

Scala內置集合已經在Numeric.scala中實現了類似的東西。你可以直接使用它們。有些東西(來自TraversableOnce.scala):

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

是的,我徘徊於這些抽象概念之中,但有些奇怪的普通操作(如/沒有定義它們)。 – 2013-05-24 09:42:34