Take a concrete method for instance,
def df(f: Float => Float, dt: Float) = (t: Float) => f(t + dt) - f(t)
It can be compiled and works. However, when I tried to define it in a generic way,
def df[T](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)
The compiler said,
"error: type mismatch; found : T;required: String def df[T](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)".
It seemed like the type T couldn't be added. Then I tried another way,
def df[T <: Double](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)
Again It failed,
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)
^
Now All my tricks have been exhausted.
How can I make it?
Regarding your first definition:
def df[T](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)
This cannot be because we cannot know if there is a "+" or a "-" method for type T.
Your first definition,
def df[T <: Double](f: T => T, dt: T) = (t: T) => f(t + dt) - f(t)
Short story - cannot extend from Double
and even if you could the +
method expects another double, not a T
.
To do this generically we need a unifying trait that applies to all numeric types and which declares all the numeric operators. Unfortunately, this isn't the case in Scala. But we have the next best thing: type classes (see this question for some info: What are type classes in Scala useful for?). Type classes are implemented in Scala using implicits.
The solution for you would be:
def df[T](f: T => T, dt: T)(implicit num: Numeric[T]) = (t: T) => num.minus(f(num.plus(t, dt)), f(t))
The method is generic, but it also requires the presence of an object num
which knows how to do things like plus
, minus
and so forth on objects of type T
and which is passed implicitly. Fortunately, the Scala library provides instances of Numeric
for all primitive numeric types Int, Double etc so you don't have to.
LATER EDIT:
As Jesper Nordenberg and Régis Jean-Gilles point out you can actually get your initial expression using an import:
def df[T](f: T => T, dt: T)(implicit num: Numeric[T]): (T => T) = {
import num._
(t: T) => f(t + dt) - f(t)
}
This is achieved using an implicit conversion also.
You can check the source file for Numeric
for more information about what's going on: Numeric.scala
You should be careful though. This solution may have performance problems if you're doing heavy mathematical computation, mostly because of boxing.
Hope it helps !