2015-09-26 145 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 
相關問題