这是我的代码片段:
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")}")
Run Code Online (Sandbox Code Playgroud)
当我运行它时,它打印"abc"而不是"ABC".我在这做错了什么?
PS
但是,如果我运行下一个代码
implicit val n: Int = 100
def add(n1: Int)(implicit n2: Int) = n1 + n2
add(7)
Run Code Online (Sandbox Code Playgroud)
所有隐含的魔法都很好.
通常这会起作用.编译器会通过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)
Run Code Online (Sandbox Code Playgroud)
但是你的问题是,范围中还有另一个隐含的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")
Run Code Online (Sandbox Code Playgroud)
实际上,有一个隐含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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
76 次 |
| 最近记录: |