3

I am trying to get a simple piece of functionality to work where I have a List of Lists and I want to do some mathematical operations on the data (-, + , *, /). I want the method to take any of the following types (Int, Float, Double).

here is what I have tried:

def doSomething[T](data: List[T]){
 data reduceLeft(_ / _)
}

the following is displayed: value / is not a member of type parameter T.

How do I get this to work for the AnyVal types (Double, Int, Float)?

Update I tried implementing the suggestion in the following code:

def dot[T](l: List[List[T]])(implicit num: Numeric[T]) = 
{

    for (row <- data)
        yield for(col <- l)
            yield row zip col map {a => num.times(a._1 , a._2)}   reduceLeft (_+_)

and get the error: type mismatch; found : a._1.type (with underlying type T) required: T

Is there any way to get around that?

Dan_Chamberlain
  • 311
  • 4
  • 10
  • what is `data` in your first `for` ? – fehu Jan 18 '11 at 14:21
  • sorry data is a List[List[T]]. – Dan_Chamberlain Jan 18 '11 at 22:53
  • i figured out one way to do this was to have it contained within a parameterized class. But, I am still wondering why the above doesn't work? Especially if I wanted to use this method as a Function Object. – Dan_Chamberlain Jan 18 '11 at 23:25
  • It seems it doesn't work because `times` requires both arguments to be of the same type T, in this case there is no ensurance that `data`'s underlying type T and `dot`'s type T are the same type. If you want to avoid parameterized class, try passing to function `data` parameter as well – fehu Jan 19 '11 at 00:38
  • for example `def dot[T](data: List[List[T]])(l: List[List[T]])(implicit num: Numeric[T]) = ...`, then use `dot(data) _` – fehu Jan 19 '11 at 00:52
  • Very nice! Thanks for the example. – Dan_Chamberlain Jan 19 '11 at 03:42
  • Interesting, type bounds on `T` like `<% Double` or `<: Numeric[T]` do not work immediately, not even for `+`. Wonder why. – Raphael Jan 19 '11 at 06:51
  • btw, you may also try `implicit val data = List(List(1, 2, 3))`; `def dot[T](l: List[List[T]])(implicit num: Numeric[T], data: List[List[T]]) = for (row <- data) yield for(col <- l) yield row zip col map {a => num.times(a._1 , a._2)} reduceLeft (num.plus(_,_))` – fehu Jan 20 '11 at 00:07

1 Answers1

9

For division:

def foo[T](l: List[T])(implicit num: Numeric[T]) = num match{
     case i: Integral[_] => l reduceLeft (i.quot(_, _))
     case fr: Fractional[_] => l reduceLeft (fr.div(_, _))}

For +, - and * it's easier (plus, minus, times respectively):

def foo[T](l: List[T])(implicit num: Numeric[T]) = l reduceLeft (num.plus(_, _))
fehu
  • 457
  • 2
  • 8
  • 2
    It should be mentioned that what you see here is often called the "(Implicit) Type Class Pattern". See e.g. http://java.dzone.com/articles/scala-implicits-type-classes – Landei Jan 17 '11 at 08:12
  • Now the trouble appears to be with using tuple values with Numeric. I have updated my example to show the issue. – Dan_Chamberlain Jan 18 '11 at 01:23