I'm trying to define a generic add function to numeric values:
def add[A](x:A, y:A): A = {
x + y
}
console:16: error: type mismatch;
found : A
required: String
x + y
^
What's the compiler complaining about?
Some of the stuff I've googled does not quite make sense to me at this moment.
Since you define A with no boundaries and no extra information, it could be any type, and not any Scala type has a + method - so this can't compile.
The error message is a result of the compiler's attempt to implicitly convert x into a String (because String has a + method, and every type can be converted to string using toString), but then it fails because y isn't a string.
To create a method for all numeric types, you can use the Numeric type:
def add[A](x:A, y:A)(implicit n: Numeric[A]): A = {
n.plus(x, y)
}
add(1, 3)
add(1.4, 3.5)
EDIT: or an equivalent syntax:
def add[A: Numeric](x:A, y:A): A = {
implicitly[Numeric[A]].plus(x, y)
}
To be able to do something like this the compiler needs to know that A has a method
def +(a: A): A
so ideally you would want to do something like
def add[A :< Numeric](x:A, y:A): A = { ...
but you can't because the numeric types in Scala have no common super type (they extend AnyVal). Look here for a related question.
Related
lately I've decided to port my project's codebase to Scala for performance reasons but just as I was getting started, I was stopped by an error I did not understand. This is the minimal amount of code that causes the error:
class Foo[A](var x: A) {
def +(other: Foo[A]) = new Foo[A](this.x + other.x)
}
And the error itself:
test.scala:2: error: type mismatch;
found : A
required: String
def +(other: Foo[A]) = new Foo[A](this.x + other.x)
^
After looking around, I found some forum posts about similar errors which were apparently caused by Scala implicitly converting the template type to a string(?).
As mentioned in the comments, the compiler doesn't have enough information about type A to know how to + two of them.
The reason for the confusing error message is that the compiler "knows" that everything has a toString() method and that type String has a + method. So why doesn't it convert both to type String and + them together? It's because the A-to-String transition is an implicit conversion and the compiler won't do more than one implicit conversion in order to resolve an expression.
Thus the found:A, required:String error. The compiler is saying, "I've already converted the first A to String in order to resolve the + method but, now that I've done that, I can't do it again on the 2nd A element."
There are a few different ways around this. Here's one.
class Foo[A:Numeric](var x: A) {
def +(other: Foo[A]) =
new Foo[A](implicitly[Numeric[A]].plus(this.x, other.x))
}
A is restricted to types found in the Numeric type class. To add two As together, pull the implementation for Numeric[A] out of the implicit scope and invoke its plus() method.
The problem here is that the plus method in this.x + other.x is not the plus method defined in Foo[A]. It comes from A. And as A is still undefined, can be Any. The compiler, as always, will look a way to make things compile and in this case will find a conversion that will allow this.x call to + method. It will find this in Predef.scala that is in scope and has
implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def +(other: String): String = String.valueOf(self) + other
}
Therefore if this.x is a String to be able to concatenate that.x, it should also be a String. Which is not the case.
You can check it in https://github.com/scala/scala/blob/706ef1b291134a5e5bce2275df2c222261f73451/src/library/scala/Predef.scala#L381
Reduced example:
class Factory(x : Int) {
def apply(y : Int)(z : Int) : Int = x + y + z
}
class Sample {
def get[B <% Int](x : B) = new Factory(x)
}
val s = new Sample
What I want: s.get(2)(3)(4) should output 9. What I get
error: type mismatch;
found : Int(3)
required: Int => Int
s.get(2)(3)(4)
^
It is perfectly correct, compiler fails as it should. The second parameter list should contain implicit conversion, but it is omitted. Hence the error arises.
The question is how to make the compiler know that is should perform implicit resolution.
Things I've tried that does not work:
s.get(2)()(3)(4)
{s get 2}(3)(4)
(s get 2)(3)(4)
((s get 2))(3)(4)
Explicit way works, but it requires two lines instead of one:
val b = s get 2
b(3)(4)
I could also use the apply method explicitly: s.get(2).apply(3)(4) But it looks ugly.
How can I make compiler perform implicit resolution inside an expression?
You can use an explicit type ascription
val nine = (s.get(2): Factory)(3)(4)
Or if you find this inconvenient, build your own control structure for forcing type inference:
def infer[X](z: => X): X = z
val nineAgain = infer(s get 2)(3)(4)
s.get(2)(implicitly)(3)(4)
(implicitly is just a method defined in Predef: def implicitly[A](implicit x: A) = x.)
I am beginner in scala language, I am confused with Any class in scala.
def f(x: Any) = println(x)
is above code represents that x variable can be of any datatype(example:int,string etc.)
rewritten code:
def f(x:Any)=x+5
<console>:13: error: type mismatch;
found : Int(5)
required: String
def f(x:Any)=x+5
if x can accept any type then why am I getting above error. I might confused understanding of any in scala. Please correct me.
In a statically typed language you can only call a method m on a value x of type A if m is defined by A. By the nature of Any, there aren't any useful methods on Any that you could call (except a few things like toString or hashCode), certainly no plus operation is defined. Imagine you passed a Boolean into that method, which is allowed since Boolean is a sub-type of Any. If the compiler allowed your code, it would run into a problem, because there is no such thing as + on a Boolean. In a dynamically typed language you could run that code and would then encounter a runtime error.
The error message looks weird, because you can concatenate strings with + and due to an implicit conversion it is possible to concatenate things with strings:
def f(x: Any) = x + "hello" // implicitly converts x to a string
f(true) // "truehello"
This is a source of great confusion and hopefully will disappear from the language. If you used a different method, the error would be more obvious:
def f(x:Any)=x-5
<console>:54: error: value - is not a member of Any
def f(x:Any)=x-5
^
If you look at println() sources you will see:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
where String.valueOf is
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Class Any already has toString method but doesn't have + method (you know that all operators such +, - etc. are methods, see http://tomjefferys.blogspot.com/2011/11/operator-overloading-in-scala.html).
I wish to write a function that operates on any value that can be added to other members of its own type (whatever "added" means in context). The obvious (heh-heh) definition of such a type:
type Addable = { def +(a : Addable) : Addable }
That gives me an error I don't understand at all: recursive method + needs result type
Why isn't that last : Addable the result type? Why does it think + is recursive anyway?
But I found a more general problem, trying to refer to a type inside its own definition:
type T = { def f: T }
But then I had a brain-wave: solve it the way I would in Java!
type T[T] = { def f: T }
This compiled!
But now I have two more problems.
First, I have no idea how to use type T. In particular,
def n(a:T) = a.f
gives the wholly sensible yet frustrating "type T takes type parameters" error.
Second, attempting to apply this pattern to the original problem
type Addable[Addable] = { def +(a : Addable) : Addable }
leads to a completely incomprehensible "Parameter type in structural refinement may not refer to an abstract type defined outside that refinement". (The actual problem is not that it's "+" -- thank God and Martin, since that would complete mess up my head -- just that it takes an Addable as a parameter.)
So
How do I define a duck-type meaning "has a particular function returning a value of the same type"?
How do I define a duck-type meaning "has a particular function taking a expression of the same type as a parameter"?
I have a religious-like belief that this problem is solvable.
Those are different Ts.
scala> type T[T] = { def f: T }
defined type alias T
scala> var x: T[Int] = null
x: T[Int] = null
scala> x = new AnyRef { def f = 5 }
x: T[Int] = $anon$1#44daa9f1
When you write:
type Addable[Addable] = { def +(a : Addable) : Addable }
You have a type Addable which takes a single type parameter, also called Addable. Here's a similar variation people often confuse themselves with.
scala> def f[Int](x: Int) = x * x
<console>:7: error: value * is not a member of type parameter Int
def f[Int](x: Int) = x * x
^
The actual answer to your question is "you can't" but I would hate to shatter your religious-like faith so instead I'll say "structural types work in mysterious ways." If you want to go on a religious mission you might visit here, which explains why you can't.
http://article.gmane.org/gmane.comp.lang.scala/7013
I'm just getting started with Scala and something which I think should be easy is hard to figure out. I am trying to implement the following function:
def square(x:Int):Int = { x * x }
This works just fine, but if I want to try to make this function work for any kind of number I would like to be able to do the following:
def square[T <: Number](x : T):T = { x * x }
This complains and says: error: value * is not a member of type parameter T
Do I need to implement a trait for this?
That was one of my first questions in Stack Overflow or about Scala. The problem is that Scala maintains compatibility with Java, and that means its basic numeric types are equivalent to Java's primitives.
The problem arises in that Java primitives are not classes, and, therefore, do not have a class hierarchy which would allow a "numeric" supertype.
To put it more plainly, Java, and, therefore, Scala, does not see any common grounds between a Double's + and a an Int's +.
The way Scala finally got around this restriction was by using Numeric, and its subclasses Fractional and Integral, in the so-called typeclass pattern. Basically, you use it like this:
def square[T](x: T)(implicit num: Numeric[T]): T = {
import num._
x * x
}
Or, if you do not need any of the numeric operations but the methods you call do, you can use the context bound syntax for type declaration:
def numberAndSquare[T : Numeric](x: T) = x -> square(x)
For more information, see the answers in my own question.
You can define square as:
def square[T: Numeric](x: T): T = implicitly[Numeric[T]].times(x,x)
This approach has the advantage that it will work for any type T that has an implicit conversion to Numeric[T] (i.e. Int, Float, Double, Char, BigInt, ..., or any type for which you supply an implicit conversion).
Edit:
Unfortunately, you'll run into trouble if you try something like List(1,2,3).map(square) (specifically, you'll get a compile error like "could not find implicit value for evidence parameter of type Numeric[T]". To avoid this issue, you can overload square to return a function:
object MyMath {
def square[T: Numeric](x: T) = implicitly[Numeric[T]].times(x,x)
def square[T: Numeric]: T => T = square(_)
}
Hopefully someone with a better understanding of the type inferencer will explain why that is.
Alternatively, one can call List(1,2,3).map(square(_)), as Derek Williams pointed out in the scala-user mailing list thread.