Scala 中的双向隐式转换

Bidirectional implicit conversion in Scala

考虑以下通用函数:

def compare[I:Ordering,T:Ordering](i:I,t:T):Int

它应该将类型 I 的值与类型 T 的值进行比较,假设它们都定义了排序。如果有一种方法可以将 I 隐式转换为 T,或将 T 隐式转换为 I,则比较应该有效。显然,如果使用类型 I 和 T 而没有任何两种转换,编译器应该会报错。

我很想写这样的东西:

def compare[I:Ordering,T:Ordering](i:I,t:T)(implicit c1:I=>T, c2:T=>I):Int

但这实际上要求存在两种转换,而不是至少一种。

有什么想法吗?

编辑:鉴于我想让问题完整的评论。如果两种隐式转换都存在,我想在这些类型中假定一个优先级。然后使用更高优先级的隐式转换进行比较。

我最初写的错误答案: 当然它会问,因为你正在尝试比较两个不同的顺序。 T:Ordering 意味着范围内应该有一个 Ordering[T] 可用。 Ordering[T] 不同于 Ordering[I]。这就像比较数字和字符串,两者可以不同地排序,但一起排序没有意义。

PS:数字和字符串可以一起排序,但这意味着数字和字符串在这里将代表相同的数据类型,并且对于该数据类型只有一个 Ordering 实例。

更好的答案: 使用包装器 class 定义转换器

object Main extends App {
  def compare[I: Ordering, T: Ordering](i: I, t: T)(implicit wrapper:   Wrapper[I, T]): Int = {
    val converter: Either[(I) => T, (T) => I] = wrapper.getConverterBasedOnPriority
    val convertedValue = if(converter.isLeft){
      converter.left.map(c => c(i))
    } else{
      converter.right.map(c => c(t))
    }
    // do what ever you want
    1
  }

  val iToT: (Int => String) = i => i.toString
  val tToI: (String => Int) = s => s.toInt

//  implicit def iToTWrapper = new Wrapper[Int , String ](iToT, null)
  implicit def tToIWrapper = new Wrapper[Int , String ](null, tToI)

  compare(1, "a")
}

class Wrapper[I, T](iToT: I => T, tToI : T => I) {
  def getConverterBasedOnPriority:Either[I => T, T => I]   = {
    // return ordering based on priority check.
    // returning iToT for example sake. Do the priority check and return accordingly
    Left(iToT)
  }
}

如果您取消注释这两个隐式,它将抛出错误。如果您对这两个隐式都进行注释,它将抛出错误。