Scala 隐式转换和箭头

scala implicit convertion and arrow

我正在为我的 DSL 构建尝试而苦苦挣扎

我的方法应该采用多对 (A, B),理想情况下我正在寻找这种代码:

myMethod(
  a1 -> b1,
  a2 -> b2,
  a3 -> b3)

我的 A 和 B 类 碰巧经常用一个字符串参数构造,所以我添加了如下所示的隐式转换器:

implict def stringToA(s: String): A = new A(s)
implict def stringToB(s: String): B = new B(s)

但是箭头运算符(用于对构造)不选择隐式转换器:

object Test {
  case class A(s: String)
  case class B(s: String)

  def myMethod(pairs: (A, B)*): Unit = Unit

  implicit def stringToA(s: String): A = A(s)
  implicit def stringToB(s: String): B = B(s)

  myMethod(new Tuple2("a", "b")) // works just fine
  myMethod("a" -> "b") // Error: Type mismatch, expected: (Test.A, Test.B), actual: (String, String)
}

有什么想法吗?

通过隐式转换(any2ArrowAssoc in scala.Predef),-> 方法可用于所有 Scala 类型。出于理智的原因,Scala 不允许在同一表达式上对 "chain" 进行多次隐式转换。你可以:

  • 在您的 A class 上定义一个明确的 -> 方法。不幸的是,由于默认的隐式转换会与此冲突,因此您可能必须使用 -Yno-predef 构建代码以避免冲突
  • 在您的 A class 上定义一个方法,其名称在外观上相似且不冲突,例如~>»
  • 如果您喜欢这种语法,请调用 myMethod(("a", "b"))(直接支持这种语法,而不是通过隐式转换)
  • myMethod接受(String, String)*并在里面做AB的转换
  • 编辑:您还可以按照@BenReich 的建议定义从(String, String)(A, B) 的隐式转换。

您可以定义从 (String, String) 到 (A, B) 的隐式转换:

implicit def toABTuple(in: (String, String)) = (A(in._1), B(in._2))   

它失败了,因为它在应用你的隐含函数之前转换为一个元组,所以它不再是一个普通的字符串 -> A/B。