2

Being new to Scala, I was playing around with fold, reduce and scan. I wanted to see the sequence in which elements are passed on the the function parameter and how the final result was being assembled. Since I planned to use it on lists of numbers and strings, I defined the following helper function with a type parameter:

scala> def vizAdd[A](p1:A, p2:A):A = {
 |   val res:A = p1 + p2
 |   println( s" * ($p1, $p2) => $res" )
 |   res
 | }
<console>:8: error: type mismatch;
 found   : A
 required: String
       val res = p1 + p2
                      ^

Post Addition with generic type parameter in Scala suggest a solution, focusing on the fact that the + method should require a numeric type to operate on, so adding an implicit parameter of type Numeric[A] to the method should do the trick. Unfortunately:

scala> def vizAdd[A](p1:A, p2:A)(implicit n: Numeric[A]):A = {
 |   val res:A = p1 + p2
 |   println( s" * ($p1, $p2) => $res" )
 |   res
 | }
<console>:8: error: type mismatch;
 found   : A
 required: String
         val res:A = p1 + p2
                          ^

The syntax with [A:Numeric] in stead of (implicit n: Numeric[A]) doesn't work either...

Compiling the singleton object “GenericTest” as implemented in the mentioned post (code below) results in the same error: “found: A, required: String”.

object GenericTest extends App {
  def func1[A](x: A, y: A)(implicit n: Numeric[A]): A = x + y    
}

What am I missing here?

I'm using Scala 2.11.5

Community
  • 1
  • 1
sTievie
  • 65
  • 7

1 Answers1

4

The Numeric trait has methods like plus, times, etc, which are used like this:

def func1[A](x: A, y: A)(implicit n: Numeric[A]): A = n.plus(x, y) 

What you're looking for is an implicit conversion that enriches A to have the infix operations like +, *, etc. i.e., this one:

import scala.math.Numeric.Implicits.infixNumericOps

def func1[A](x: A, y: A)(implicit n: Numeric[A]): A = x + y

Or more with a little syntactic sugar:

def func1[A: Numeric](x: A, y: A): A = x + y 
Michael Zajac
  • 55,144
  • 7
  • 113
  • 138
  • Thank you, the `import` statement was what I was missing :-) A follow up question though: initially I also wanted to use the "vizAdd" function with String parameters, which (to me) made sense since they also have an infix `+` method defined. Is there an easy/elegant way to modify the "vizAdd" function so that it also accepts String parameters? Or does this require some kind of type matching to differentiate the implementation between real numerical parameters and String parameters? – sTievie Mar 01 '15 at 22:03
  • 1
    @sTievie While `String` does have a `+` method defined, it doesn't have other important methods that `Numeric` has, so it doesn't really fit. You can hack it by defining some `Numeric[String]`, but I'm not sure how useful that would be. – Michael Zajac Mar 01 '15 at 22:32
  • I'm new to scala. Trying to enhance `def add[A](x: A, y: A)(implicit numeric: Numeric[A]): A = numeric.plus(x, y)` to handle strings. If numeric, then return the number, otherwise 0. I tried to define an implicit conversion from String to Numeric : `implicit def toStr(s: String): Numeric[Double] = Try(s.toDouble).getOrElse(0)` but doesn't compile. Can you please explain why and provide the correct syntax – mbsf Jun 03 '22 at 17:54