在函数应用程序上找不到隐式参数

ssa*_*anj 5 scala function implicit-conversion

如果我定义仅将数字作为以下内容的打印功能:

def print[T <% Number](value:T) {}
print: [T](value: T)(implicit evidence$1: (T) => java.lang.Number)Unit
Run Code Online (Sandbox Code Playgroud)

我可以通过以下方式致电上述内容:

print(5)
print(5.5)
print(6L) 
Run Code Online (Sandbox Code Playgroud)

但不能使用字符串:

print("aaa")  
<console>:7: error: could not find implicit value for evidence parameter of type (java.lang.String) => java.lang.Number
       print("aaa")
Run Code Online (Sandbox Code Playgroud)

这是预期的。

但是,如果我将打印功能定义为:

def print2[T <% Number]: T => Unit = value => { } 
print2: [T](implicit evidence$1: (T) => java.lang.Number)(T) => Unit
Run Code Online (Sandbox Code Playgroud)

注意隐式参数是第一个参数而不是最后一个参数。

如果我尝试手动定义以上功能:

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 =  { }
Run Code Online (Sandbox Code Playgroud)

基本上,以上不是有效的函数定义,但是编译器在我先前定义print2时创建了它。

当我用Int调用print2时:

print2(5)
<console>:7: error: type mismatch;
 found   : Int(5)
 required: (?) => java.lang.Number
       print2(5)
Run Code Online (Sandbox Code Playgroud)

如果我将其参数化:

print2[Int](5)
<console>:7: error: type mismatch;
 found   : Int(5)
 required: (Int) => java.lang.Number
       print2[Int](5)
Run Code Online (Sandbox Code Playgroud)

似乎找不到来自scala.Int => java.lang.Integer的隐式转换。

如何重新定义print以使其返回函数并以正确的方式访问隐式?

Dan*_*ral 6

这里的问题是您要传递5 作为隐式参数。

现在,我在计算机上,进行了一些更正:

def print[T <% Number](value:T) {}
Run Code Online (Sandbox Code Playgroud)

您将其称为函数,但这是一种方法

def print2[T <% Number]: T => Unit = value => { }
Run Code Online (Sandbox Code Playgroud)

同样,您将此称为函数。其实,这是一个方法,其返回的功能。该方法接收一个类型参数T,和一个隐式参数。

print2(5)
Run Code Online (Sandbox Code Playgroud)

因此,在这里,您将print2传递的方法5称为隐式参数。T尚未推断出类型,因为它首先尝试符合5期望的类型T => Number。但是,由于5不符合Function1[T, Number],因此即使不进行推断也会失败T

有很多打电话的方法print2。例如:

print2(implicitly[Int => Number])
print2[Int]
(print2: Int => Unit)
val f: Int => Unit = print2
Run Code Online (Sandbox Code Playgroud)

但是,要调用返回的函数,print2必须避免使方法(5)看起来像隐式参数print2。实际上,上面只有一种情况需要不同的东西:

print2(implicitly[Int => Number])(5)
print2[Int].apply(5)
(print2: Int => Unit)(5)
val f: Int => Unit = print2; f(5)
Run Code Online (Sandbox Code Playgroud)

现在,这些示例大多数都具有显式(而不是推断的)类型参数。让我们考虑一下如果没有它会发生什么:

print2.apply(5)
Run Code Online (Sandbox Code Playgroud)

由于没有参数传递给print2它,因此它选择符合界限的最具体类型T。由于T没有界限,Nothing所以选择。然后尝试查找隐式Nothing => Unit。因为没有这样的隐式,所以失败了。

print2永远不会寻找函数返回的参数来帮助类型推断。