Take the following code as an example:
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")
}
How can I get the behavior of TupleMaker (specially w.r.t. implicit conversions), but with an inline function? I can modify both class A and B, and use any infix operator (doesn't have to be an existing one) if that helps the solution.
You can add one more conversion
implicit def tupleToTuple(a: (A, A)): (B, B) = (atob(a._1), atob(a._2))
More generic solution is
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
Simpler
implicit def tupleToTuple[X, Y, X1, Y1](t: (X, Y))(implicit
ev1: X => X1,
ev2: Y => Y1
): (X1, Y1) = (t._1, t._2)
doesn't work because X
is inferred first (to be A
). So ev: T <:< (X1, Y1)
is a trick to make X1
, Y1
be inferred first (to be B
). Implicits are resolved from the left to the right.