2013-07-29 15 views
2

更先進的數學最近,我(終於)使用Scala的數字特徵,這沒有奇蹟開始。例如:與Scala的數字和小數

def square[A](x: A)(implicit num: Numeric[A]): A = num.times(x, x) 

現在我能夠勇敢地正視任意數量的是它DoubleIntegerBigDecimal,或什麼不是。但是如果我想要做更高級的數學呢?例如,我的logistic functionDouble數字看起來是這樣的:

def logisticFunction(x: Double): Double = 1.0/(1.0 + math.exp(-x)) 

我能做的增加,容易分割(我只需要使用特質Fractional代替Numeric),但什麼指數?我當然不想寫我自己的exp函數(或任何採用Double參數的任意函數)。

所以,我的問題是這樣的:我如何將我的A轉換爲Double,按照我的數學,然後轉換回A。它甚至有可能嗎?

編輯:

這是我的函數的簽名應該如何看起來像:

def logisticFunction[A](x: A)(implicit num: Fractional[A]): A = 
    /* Magic happens here */ 

我已經想通了部分有關轉換翻一番,這是因爲num.toDouble(x)一樣容易。然而,轉換回A的問題依然存在。

+2

的logisticFunction是永遠不會返回A的有效成員,例如,整數,所以不,我不明白它是如何可能的,除非你想開始使用它作爲部分應用函數,並修改它以匹配函數的有效數字類型。 – Shadowlands

+1

'導入Numeric.Implicits._'並寫入'x * x'而不是'num.times(x,x)'。 –

+0

對不起,很顯然,但我假設在這裏工作有更復雜的應用程序?爲什麼你會使用數字來編寫這些函數?它們有多簡單?我這樣說是因爲說實話,你想避免日常使用的Scala的大部分特性,請相信我這些很多功能,如隱含在強大的金融系統中沒有地位。 –

回答

6

我仍然懷疑這種做法是非常有用的。但隨着你的描述,你會想是這樣的:

type FromDouble[A] = Double => A 
type ToDouble [A] = A => Double 

def logisticFunction[A: FromDouble: ToDouble](x: A): A = 1.0/(1.0 + math.exp(-x)) 

logisticFunction(0.5) 
implicit def bigDecimalToDouble(b: BigDecimal) = b.toDouble  
logisticFunction(BigDecimal(0.5)) 

或用專用型類:

object FromDouble { 
    implicit object _Double extends FromDouble[Double] { 
    def apply(d: Double) = d 
    } 
    implicit object _BigDecimal extends FromDouble[BigDecimal] { 
    def apply(d: Double) = BigDecimal(d) 
    } 
} 
trait FromDouble[A] extends (Double => A) 

object ToDouble { 
    implicit object _Double extends ToDouble[Double] { 
    def apply(d: Double) = d 
    } 
    implicit object _BigDecimal extends ToDouble[BigDecimal] { 
    def apply(b: BigDecimal) = b.toDouble 
    } 
} 
trait ToDouble[A] extends (A => Double) 

def logisticFunction[A: FromDouble: ToDouble](x: A): A = 1.0/(1.0 + math.exp(-x)) 

logisticFunction(0.5) 
logisticFunction(BigDecimal(0.5)) 
3

您將需要一個類型的類,它提供三角函數如exp。 Scala的標準庫不會超越Fractional。您可以嘗試使用Spire

例子:

$ sbt core/console 

import spire.math._ 
import spire.algebra._ 
import spire.implicits._ 

def logisticFunction[A](x: A)(implicit m: Field[A], t: Trig[A]): A = 
    m.one/(m.one + exp(-x)) 

logisticFunction(0.5) 
logisticFunction(BigDecimal(0.5)) 
+0

我的問題與數字沒有太大的關係,我想創建一個接受任何小數(Double,Float,BigDecimal)數字的泛型方法,並與它進行數學運算並返回相同類型的結果。操作(+,*等),但不能與接受雙精度的任意函數一起使用 –

+0

然後,您需要爲來自Double的轉換類型類,儘管看起來很奇怪,如果您用「Double」進行數學轉換,並回到首位 –