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)
}
}
如果您取消注释这两个隐式,它将抛出错误。如果您对这两个隐式都进行注释,它将抛出错误。
考虑以下通用函数:
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)
}
}
如果您取消注释这两个隐式,它将抛出错误。如果您对这两个隐式都进行注释,它将抛出错误。