如何最低限度地调和 Scala 的 @specialized 和 java.lang.Comparable?
How to minimally reconcile Scala's @specialized and java.lang.Comparable?
我有第三方 Java API 使用这样的方法(简化):
public <C extends Comparable<C>> C jFoo(C c);
我想写一个这样的包装器:
def foo[C <: Comparable[C]](c: C): C = jFoo(c)
为了允许包装器方法接受原语(因为据我所知,无论如何都会发生装箱,所以这不相关),我想专门化 C
:
def foo[@specialized(Int, Double) C <: Comparable[C]](c: C): C = jFoo(c)
但是,scalac 抱怨说,由于参数的上限,该方法无法专门化。
一个解决方案是添加一个证据参数:
def foo[@specialized(Int, Double) C, CC <: Comparable[CC]](c: C)
(implicit evComp: C => CC): CC =
jFoo(evComp(c))
这有效,您现在可以调用:
foo(2.0)
但是,方法签名 - API 的一部分 - 现在并不是真正可读的。
在方法级别是否有替代方法可以产生等效的、更具可读性的签名,同时保持专业化?
(Scala 2.12.x 很好,Dotty 没那么多)
您可以通过使第二个类型参数 CC
成为特殊 EvC
类型 class.
的类型成员来摆脱它
以下作品:
import java.lang.Comparable
def jFoo[C <: Comparable[C]](c: C): Unit = println("compiles => ship it")
trait EvC[C] {
type CC <: Comparable[CC]
def apply(c: C): CC
}
def foo[@specialized(Int, Double) C](c: C)(implicit evC: EvC[C]): Unit =
jFoo[evC.CC](evC(c))
implicit object DoubleEvC extends EvC[Double] {
type CC = java.lang.Double
def apply(c: Double) = (c: java.lang.Double)
}
foo(42.0) // compiles => ship it
在某种意义上,我只是将 C => CC
部分与类型参数 CC
本身粘合在一起,因此类型 CC
不再出现在类型参数中列表。我不确定你是否可以完全摆脱所有这些,内置原始类型没有实现 java.lang.Comparable
.
仍然是事实
我有第三方 Java API 使用这样的方法(简化):
public <C extends Comparable<C>> C jFoo(C c);
我想写一个这样的包装器:
def foo[C <: Comparable[C]](c: C): C = jFoo(c)
为了允许包装器方法接受原语(因为据我所知,无论如何都会发生装箱,所以这不相关),我想专门化 C
:
def foo[@specialized(Int, Double) C <: Comparable[C]](c: C): C = jFoo(c)
但是,scalac 抱怨说,由于参数的上限,该方法无法专门化。
一个解决方案是添加一个证据参数:
def foo[@specialized(Int, Double) C, CC <: Comparable[CC]](c: C)
(implicit evComp: C => CC): CC =
jFoo(evComp(c))
这有效,您现在可以调用:
foo(2.0)
但是,方法签名 - API 的一部分 - 现在并不是真正可读的。
在方法级别是否有替代方法可以产生等效的、更具可读性的签名,同时保持专业化?
(Scala 2.12.x 很好,Dotty 没那么多)
您可以通过使第二个类型参数 CC
成为特殊 EvC
类型 class.
以下作品:
import java.lang.Comparable
def jFoo[C <: Comparable[C]](c: C): Unit = println("compiles => ship it")
trait EvC[C] {
type CC <: Comparable[CC]
def apply(c: C): CC
}
def foo[@specialized(Int, Double) C](c: C)(implicit evC: EvC[C]): Unit =
jFoo[evC.CC](evC(c))
implicit object DoubleEvC extends EvC[Double] {
type CC = java.lang.Double
def apply(c: Double) = (c: java.lang.Double)
}
foo(42.0) // compiles => ship it
在某种意义上,我只是将 C => CC
部分与类型参数 CC
本身粘合在一起,因此类型 CC
不再出现在类型参数中列表。我不确定你是否可以完全摆脱所有这些,内置原始类型没有实现 java.lang.Comparable
.