Here is my code snippet:
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")}")
When I run it, it prints "abc" instead of "ABC". What am I doing wrong here?
PS
However, if I run the next code
implicit val n: Int = 100
def add(n1: Int)(implicit n2: Int) = n1 + n2
add(7)
all implicit magic works just fine.
Normally this would work. The compiler would implicitly convert the implicit method to a function through eta-expansion. Say, if I wanted to require an implicit Int => List[Int]
for some reason.
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)
But your problem is that there is another implicit String => String
already in scope that comes from Predef
. Namely =:=[String, String]
, which extends String => String
. Because this already exists in scope as a function, the compiler sees no need to look for anything else. And, if you convert your implicit method to an implicit function, you will get an ambiguous implicits error:
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")
Really though, having an implicit String => String
is probably not a good idea. Use a type class that wraps a function, instead.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With