1

以一个具体的方法为例,

def df(f: Float => Float, dt: Float) = (t: Float) => f(t + dt) - f(t)

它可以编译和工作。但是,当我尝试以通用方式定义它时,

def df[T](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)

编译器说,

“错误:类型不匹配;找到:T;必需:String def df[T](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)” .

似乎无法添加类型 T。然后我尝试了另一种方法,

def df[T <: Double](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)

又失败了,

scala> def df[T <: Double](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)
<console>:7: error: type mismatch;
 found   : Double
 required: T
       def df[T <: Double](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)
                                                             ^

现在我所有的把戏都用完了。

我怎样才能做到?

4

2 回答 2

2

关于您的第一个定义:

def df[T](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)

这不可能是因为我们不知道类型 T 是否存在“+”或“-”方法。

你的第一个定义,

def df[T <: Double](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)

短篇小说 - 无法扩展Double,即使您可以,该+方法也需要另一个 double,而不是T.

一般来说,要做到这一点,我们需要一个适用于所有数字类型并声明所有数字运算符的统一特征。不幸的是,在 Scala 中并非如此。但是我们有下一个最好的东西:类型类(有关一些信息,请参阅这个问题:Scala 中的类型类有什么用处?)。类型类是在 Scala 中使用隐式实现的。

您的解决方案是:

def df[T](f: T => T, dt: T)(implicit num: Numeric[T]) = (t: T) => num.minus(f(num.plus(t, dt)), f(t))

该方法是通用的,但它还需要一个对象,该对象num知道如何对类型的对象执行诸如等之类的操作plus,并且该对象是隐式传递的。幸运的是,Scala 库为所有基本数字类型 Int、Double 等提供了实例,因此您不必这样做。minusTNumeric

后期编辑:

正如 Jesper Nordenberg 和 Régis Jean-Gilles 指出的那样,您实际上可以使用导入获得初始表达式:

def df[T](f: T => T, dt: T)(implicit num: Numeric[T]): (T => T) = {
  import num._
  (t: T) => f(t + dt) - f(t)
}

这也是使用隐式转换来实现的。您可以查看源文件以Numeric获取有关正在发生的事情的更多信息:Numeric.scala

不过你应该小心。如果您进行繁重的数学计算,这个解决方案可能会出现性能问题,主要是因为装箱。

希望能帮助到你 !

于 2013-02-22T15:08:05.213 回答
1

你不能t + dt为任意类型做,T因为不能保证+存在T——事实上,大多数类型都没有定义+.

它也不起作用,T <: Double因为子类+上的方法Double返回 a Double,并f要求将 aT传递给它。

现在,您可能正在寻找一种进行通用数学的方法——也就是说,忽略传递给您的确切数字类型。这在 Scala 中并不容易做到,特别是如果您还想要性能的话。您可以访问我的这个老问题,尽管现在有更有效的方法。如果您想要效率,请查看Spire 。

于 2013-02-22T15:02:51.803 回答