[英]How can I create an inline function in scala that respects implicit conversions?
以下面的代码为例:
object Test6 {
def main(args: Array[String]): Unit = {
val a = new A
//works
takesBTuple(tupleMaker(a, a))
//does not work, because a becomes an instance of ArrowAssoc[A] instead of ArrowAssoc[B]
takesBTuple(a->a)
}
class A
class B
implicit def atob(a: A): B = new B
def tupleMaker[X, Y](x: X, y: Y): (X, Y) = (x, y)
def takesBTuple(b: (B, B)): Unit = println("taken")
}
如何获得 TupleMaker 的行为(特别是 w.r.t. 隐式转换),但使用内联 function? 如果对解决方案有帮助,我可以同时修改 class A 和 B,并使用任何中缀运算符(不必是现有的)。
您可以再添加一次转化
implicit def tupleToTuple(a: (A, A)): (B, B) = (atob(a._1), atob(a._2))
更通用的解决方案是
class A
class A1
class B
implicit def atob(a: A): B = new B
implicit def a1tob(a: A1): B = new B
implicit def tupleToTuple[T, X1, Y1, X, Y](t: (X, Y))(implicit
ev: T <:< (X1, Y1),
ev1: X => X1,
ev2: Y => Y1
): T = (t._1, t._2)
val a = new A
val a1 = new A1
takesBTuple(a -> a) // compiles
takesBTuple(a1 -> a1) // compiles
takesBTuple(a -> a1) // compiles
更简单
implicit def tupleToTuple[X, Y, X1, Y1](t: (X, Y))(implicit
ev1: X => X1,
ev2: Y => Y1
): (X1, Y1) = (t._1, t._2)
不起作用,因为首先推断出X
(为A
)。 所以ev: T <:< (X1, Y1)
是首先推断出X1
, Y1
的技巧(成为B
)。 隐式从左到右解析。
解决这个问题的简单方法是
takesBTuple((a:B) -> a)
否则,您可以定义一个具有->
作为方法的特征ConvertibleToB
,然后这将起作用。
val a = new A
val aa = new AA
//all of these work
takesBTuple(tupleMaker(a, a))
takesBTuple(a -> a)
takesBTuple(aa -> a)
takesBTuple(a -> aa)
takesConvertibleToBTuple(a -> a)
takesConvertibleToBTuple(a -> aa)
//Just for demonstration
def takesConvertibleToBTuple(t: (ConvertibleToB, ConvertibleToB)): Unit = println("took " + t)
trait ConvertibleToB {
def convertToB: B
def ->(b: B): (B, B) = (convertToB, b)
def ->(a: this.type): (this.type, this.type) = (this, a)
}
class A extends ConvertibleToB {
override def convertToB: B = new B
}
class AA extends ConvertibleToB {
override def convertToB: B = new B
}
implicit def makeB(c: ConvertibleToB): B = c.convertToB
您需要导入的唯一隐式 def 是makeB
。 不过,我不知道这是否是您想要的,或者对您是否实用,尤其是如果您不希望将(A, AA)
类型的元组转换为(B, B)
链接到 Scastie: https://scastie.scala-lang.org/pPuzw0sSQfKlglfT0a3Rrw
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.