Implicit parameter not found on function application
If I define a print function that only takes numbers as:
def print[T <% Number](value:T) {}
print: [T](value: T)(implicit evidence$1: (T) => java.lang.Number)Unit
I can call the above with:
print(5)
print(5.5)
print(6L)
But not with a String:
print("aaa")
<console>:7: error: could not find implicit value for evidence parameter of type (java.lang.String) => java.lang.Number
print("aaa")
This is expected.
But if I define the print function as:
def print2[T <% Number]: T => Unit = value => { }
print2: [T](implicit evidence$1: (T) => java.lang.Number)(T) => Unit
Notice how the implicit parameter is the first parameter instead of the last.
If I try to manually define the above function:
def print3[T](implicit f: (T) => java.lang.Number)(value:T):Unit = { }
<console>:1: error: '=' expected but '(' found.
def print3[T](implicit f: (T) => java.lang.Number)(value:T):Unit = { }
Basically the above is not a valid function definition but the compiler creates it when I previously defined print2.
When I call print2 with an Int:
print2(5)
<console>:7: error: type mismatch;
found : Int(5)
required: (?) => java.lang.Number
print2(5)
if I parameterize it:
print2[Int](5)
<console>:7: error: type mismatch;
found : Int(5)
required: (Int) => java.lang.Number
print2[Int](5)
It looks like it can't find the implicit conversion from scala.Int => java.lang.Integer.
How can I redefine print such that it returns funct开发者_如何转开发ions and also accesses implicits in the correct way?
The problem here is that you are passing 5 as the implicit parameter.
Now that I'm on a computer, a few corrections:
def print[T <% Number](value:T) {}
You call this a function, but it is a method.
def print2[T <% Number]: T => Unit = value => { }
Again, you call this a function. Actually, it is a method which returns a function. The method receives one type parameter, T
, and one implicit parameter.
print2(5)
So, here, you call the method print2
passing 5
as its implicit parameter. The type T
hasn't been infered yet because it is first trying to conform 5
to the expected type T => Number
. However, since 5
doesn't conform to Function1[T, Number]
, it fails without even inferring T
.
There are many ways to call print2
. For example:
print2(implicitly[Int => Number])
print2[Int]
(print2: Int => Unit)
val f: Int => Unit = print2
However, to call the function that is returned by print2
, you have to avoid making (5)
look like the implicit parameter to the method print2
. There's actually only one case above that needs something different:
print2(implicitly[Int => Number])(5)
print2[Int].apply(5)
(print2: Int => Unit)(5)
val f: Int => Unit = print2; f(5)
Now, most of these examples have explicit, instead of inferred, type parameters. Let's consider what would happen in its absence:
print2.apply(5)
Because no parameter was passed to print2
, it selects the most specific type that conforms to the bounds of T
. Since T
has no bounds, Nothing
is chosen. It then tries to find an implicit Nothing => Unit
. Because there's no such implicit, it fails.
The parameter to the function that would be returned by print2
is never looked into to help type inference.
精彩评论