Question

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?

Was it helpful?

Solution

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 !

OTHER TIPS

You can't do t + dt for an arbitrary type T because there's no guarantee that + exists for T -- in fact, most types do not define +.

It also doesn't work for T <: Double because the method + on Double subclasses returns a Double, and f requires that a T be passed to it.

Now, you a probably looking for a way to do generic math -- that is, ignore the exact number type passed to you. That isn't easy to do in Scala, particularly if you want performance as well. You can visit this old question of mine, though there are more efficient approaches nowadays. Look at Spire if you want efficiency.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top