I am trying to understand the type parameter concepts in scala.
def sum [A] (a:A):A={a}
// used single parameter and its working fine, able to pass any data
Let's look at this from a little different perspective: what, actually, is a parameter? What does it mean?
And let's start with something you are probably more familiar with: value parameters. What does a value parameter in a subroutine mean? Say, we have something like this:
def foo(a, b) = { /* … */ } // deliberately ignoring types and the body
It means: I have a subroutine foo with two parameters, a and b. And the subroutine is general, it doesn't care what the actual concrete values of a and b are. It works for all values of a and b because it doesn't even know what the values of a and b are.
A little more concrete:
def plus(a: Int, b: Int) = a + b
Again, plus doesn't know what the actual values of a and b are. It works for 2 and 3 just as well as for 23 and 42 or 0 and 0. It is completely and utterly ignorant of the concrete values of a and b. It only knows that a and b exist.
Now, type parameters are the same thing, just on the type level instead of the value level.
blabla[A]
means the same thing at the type level as blabla(a) means at the value level: "I have a thing, I have no idea what it is (and I don't care), but I'll call it A."
So, what you have effectively done, is to tell Scala that you don't know anything about A. But then you do something with it (or rather with its instance): you add it. But, how do you even know you can add it? You don't even know what it is!
So, adding it cannot possibly work, it must fail!
However, the way it fails is slightly strange, and has to do with some of the pre-defined implicit conversions in the scala.Predef object. In particular, there is an implicit conversion for string concatenation, which can convert an arbitrary object into a String and then concatenate another String to it. In this case, it converts a to an any2stringadd and then tries to add b to it, but the any2stringadd.+ method only takes a String as its argument, and thus you get the strange error message that it is expecting a String.
[Note that any2stringadd is deprecated in Scala 2.13, so in the future you would just get an error about a non-existent method.]
There are a couple of other similar types that sometimes pop up, when you have complex type errors:
Any, AnyRef, or AnyVal. (That would be kind of like Object in Java or C♯.)Serializable interface, so sometimes when you have two very different types where you actually expect the same type, Scala will helpfully infer Serializable as the closest common ancestor, and then yell at you for doing stuff with a Serializable that it doesn't support.Products (i.e. Product1, Product2, … Product22) and thus all Tuples (i.e. Tuple1, Tuple2, … Tuple22). Product is also mixed into all case classes. So, if you have two Tuples of different arity or two unrelated case classes (e.g. you sometimes return None but then accidentally return somethingOfTypeFoo instead of Some(somethingOfTypeFoo)), then the most precise common type between Option and your case class Foo will be deduced as Product or …Product with Serializable: it is also possible to receive a combination of the above. E.g. Tuples are Serializable, so this is actually the most precise common type of two Tuples of different arity.One common way to run into these problems is in a conditional expression without else:
if (true) 42
what type does this return? Int? No! The then branch returns Int, but the else branch returns nothing (because there is no else branch). Scala actually has a return type for not returning anything: Unit. Unit is a subtype of AnyVal, Int is a subtype of AnyVal, so the closest common ancestor of the types of the two branches of the conditional expression is actually AnyVal, not Int. (Note: the fact that the else branch is unreachable is irrelevant from a typing perspective. Reachability is a runtime thing, types are a compile time thing.)
def sum[A](a:A,b:A):A={a+b}
You are adding T + T, the compiler can't infer the + for T, it will use the default implicit +: any2stringadd, so the compiler will throw required: String error.
see https://issues.scala-lang.org/browse/SI-8229
implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def +(other: String): String = String.valueOf(self) + other
}