Ambiguous overload error when overloaded definitions differ only by implicit parameter

When using this code pattern,

class A
class B

inline def f(v: String)(using a: A) = v
inline def f(v: String)(using b: B) = v.reverse

def t =
  given b: B = new B()
  f("hello")

I’m getting the error

Ambiguous overload. The overloaded alternatives of method f with types
 (v: String)(using b: B): String
 (v: String)(using a: A): String
both match arguments (("hello" : String))

Is there a way to ignore function overloads which can not satisfy the using constraint at the call site? Or a different way to achieve a similar pattern?

My use case is inspired by the builder pattern with contextual functions.

I believe you could use implicits (givens) to achieve this. Something along the lines of

trait StringOp {
  def operate(str: String) : String
}

object StringOp {
   implicit def aOp(using A): StringOp = (str) => str
   implicit def bOp(using B): StringOp = (str) => str.reverse
}

f(str: String)(using StringOp) = summon[StringOp].operate(str)

although I would add that usually too much magic in your API can make it quite unwieldy and non-obvious

The new extension resolution SIP allows importing from different objects, the first case below.

The other cases are similar to the implicits in the other answer.

import language.experimental.relaxedExtensionImports

class A
class B

object ThingOne:
  extension (s: String)
    def f(using A): String = s*2
object ThingTwo:
  extension (s: String)
    def f(using B): String = s.reverse

object GivenThings:
  given ThingOne: AnyRef with
    extension (s: String)
      def f(using A): String = s*2
  given ThingTwo: AnyRef with
    extension (s: String)
      def f(using B): String = s.reverse

object UsingThings:
  given ThingOne(using A): AnyRef with
    extension (s: String)
      def f: String = s*2
  given ThingTwo(using B): AnyRef with
    extension (s: String)
      def f: String = s.reverse

@main def test(): Unit =
  given B = B()
  println:
    import ThingOne.*, ThingTwo.*
    "hello".f
  println:
    import GivenThings.given
    "hello".f
  println:
    import UsingThings.given
    "hello".f