考虑以下通用函数:
def compare[I:Ordering,T:Ordering](i:I,t:T):Int
它应该将类型I的值与类型T的值进行比较,假设它们都定义了Ordering。如果有一种方法可以隐式地将I转换为T,或者将T转换为I,那么比较应该有效。显然,如果使用不具有任何两种转换的类型I和T,编译器应该抱怨。
我很想写这样的东西:
def compare[I:Ordering,T:Ordering](i:I,t:T)(implicit c1:I=>T, c2:T=>I):Int
但这实际上要求两个转换都存在,而不是至少一个。
有什么想法吗?
编辑:鉴于评论,我想让问题完整。如果两个隐式转换都存在,我想假设类型之间的优先级。然后使用更高优先级的隐式转换进行比较。
答案 0 :(得分:0)
我最初写的错误答案:
当然它会问,因为你试图比较两种不同的顺序。 T:Ordering
表示范围内应该有Ordering[T]
。 Ordering[T]
与Ordering[I]
不同。这就像比较数字和字符串,两者可以不同的顺序排序,但一起排序没有意义。
PS:数字和字符串都可以一起订购,但这意味着数字和数字字符串将代表相同的数据类型,并且该数据类型只有Ordering
的一个实例。
更好的答案: 使用包装类来定义转换器
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)
}
}
如果你取消两个implicits,它将抛出并出错。如果你对两个含义都进行了评论,它就会抛出错误。