开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜