2015-09-26 99 views
4

这里是我的代码片段:为什么我的隐式函数参数不起作用?

implicit def trick(s: String): String = s.toUpperCase  
def fun(s: String)(implicit f: String => String): String = f(s)   
println(s"String is ${fun("abc")}") 

当我运行它,它打印 “ABC”,而不是 “ABC”。我在这里做错了什么?

PS

但是,如果我运行下面的代码

implicit val n: Int = 100 
def add(n1: Int)(implicit n2: Int) = n1 + n2 
add(7) 

所有隐魔法工作得很好。

回答

7

通常这会奏效。编译器会通过eta-expansion将隐式方法隐式转换为函数。说,如果我想出于某种原因需要暗示Int => List[Int]

implicit def trick(i: Int): List[Int] = List.fill(5)(i) 

def fun(i: Int)(implicit f: Int => List[Int]): List[Int] = f(i) 

scala> fun(4) 
res5: List[Int] = List(4, 4, 4, 4, 4) 

但你的问题是,是另一隐含String => String已经存在在来自Predef范围。即=:=[String, String],其延伸String => String。因为作为函数已经存在于范围中,编译器认为不需要寻找其他任何东西。 ,如果您将您的隐式方法的隐函数,你会得到一个模糊的implicits错误:

implicit val trick: String => String = _.toUpperCase 

scala> fun("abc") 
<console>:19: error: ambiguous implicit values: 
both method $conforms in object Predef of type [A]=> <:<[A,A] 
and value trick of type => String => String 
match expected type String => String 
     fun("abc") 

真的不过,有一个隐含的String => String可能不是一个好主意。相反,使用包装函数的类型类。

case class Trick[A](f: A => A) 

implicit val trick = Trick[String](_.toUpperCase) 

def fun(s: String)(implicit t: Trick[String]): String = t.f(s)   

scala> println(s"String is ${fun("abc")}") 
String is ABC 
相关问题