0
votes

I'm trying to write some code to convert an implicit argument, like the following:

case class A()
case class B()
object B {
    implicit def b2a(b: B): A = new A()
}

def foo(f: B => String) = f(new B())
def bar(implicit a: A) = "A"

foo { implicit b =>
  bar()
}

gives the error:

<console>:27: error: not enough arguments for method bar: (implicit a: A)String. 
Unspecified value parameter a.

Is there a way to use the implicit conversion without calling it manually?

1
This isn't an answer, but are you absolutely certain you need to do this? You've already seen what a confusing mess it is to have to reason about how these implicits are going to be resolved—do you really want to impose that confusion on everyone who ever uses your code? - Travis Brown
I agree. It's more trouble than it's worth for this, but I accepted @m-z's answer because it fixed the issue. - pschorf

1 Answers

2
votes

I believe this breaks the "one at a time" rule. There is no implicit A in the scope of your call to bar, only an implicit B. If the compiler tried to also implicitly convert the implicit B to an A, that would be two steps, instead of one.

However, you can work around this through implicit chaining.

implicit def a(implicit b: B): A = new A()

If this method is in scope, the compiler will see an implicit A in scope, as long as it can fill the implicit B, which it can.

scala> foo { implicit b => bar }
res1: String = A

The specific error you were having was because you needed to remove the parenthesis, which I did here. That leads to the "implicit not found" error, described above.