1
votes

i'm trying to understand the behavior of the compiler in this situation

object ImplicitTest extends App {

  def foo[T](implicit x: (String => T)): T = ???

  implicit val bar = (x: String) => x.toInt

  foo
}

the code above does not compile and gives the following error:

ambiguous implicit values: both method $conforms in object Predef of type [A]⇒ <:<[A,A] and value bar in object ImplicitTest of type ⇒ String ⇒ Int match expected type String ⇒ T

as the error says my implicit value is conflicting with another implicit defined in Predef... based on this it seems there is no way to declare an implicit parameter to a function converting a value from a known type to an unknown (generic) type.

Is this due to some technical limitation on the compiler or is just the way it is supposed to work, and i'm violating some constraints i'm not aware of?

1

1 Answers

2
votes

You're not providing a type parameter to foo when you call it (and there is no other way to infer it, for the following reason), so the compiler is having trouble finding the right one, and the right implicit.

You have the implicit bar: String => Int in scope, but you also have implicits in Predef that create instances of =:= and <:< which both extend A => B, and create implicit String => As. The compiler is looking for some implicit function String => T for foo, but it's not sure which one, and you have multiple in scope. bar will not take precedence because you haven't specified the specific String => T it's looking for.

This will work:

def foo[T](implicit x: (String => T)): T = ???

implicit val bar = (x: String) => x.toInt

foo[Int]