2

最近,我(终于)开始使用 Scala 的 Numeric trait,这确实很神奇。例如:

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

现在,我可以对任何数字求平方,无论是DoubleIntegerBigDecimal还是其他数字。但是,如果我想做一些更高级的数学怎么办?例如,我的数字逻辑函数Double如下所示:

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

我可以轻松地进行加法和除法(我只需要使用 traitFractional而不是Numeric),但是指数呢?我当然不想编写自己的exp函数(或任何带参数的任意函数Double)。

所以,我的问题是:如何将我的转换ADouble,对此进行数学运算,然后转换回A. 甚至可能吗?

编辑:

这就是我的函数签名的样子:

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

我已经弄清楚了关于转换为 double 的部分,这就像num.toDouble(x). 但是,转换回的问题A仍然存在。

4

2 回答 2

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))
于 2013-07-29T15:56:27.500 回答
4

您将需要一个提供三角函数的类型类,例如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))
于 2013-07-29T15:39:41.980 回答