我不确定我是否理解你的问题,尤其是不清楚
ContainableNumeric
implicit
参数可能是解决问题的方法。你想做的是创建一个密封的
typeclass
仅适用于您允许并要求泛型类型受该类型类约束的类。下面是一个简单的示例,说明它可能是什么样子的:
@implicitNotFound("""Cannot find implicit value for Containable[${T}]. The type ${T} is not Containable.""")
sealed trait Containable[T] {
def wrap(value: T): Container[T]
}
sealed trait ContainableComparable[T] extends Containable[T] with Ordering[T]
sealed trait ContainableNumeric[T] extends ContainableComparable[T]
object Containable {
private class ContainableImpl[T] extends Containable[T] {
override def wrap(value: T): Container[T] = new Container[T](value)(this)
}
private class ContainableNumericImpl[T: Numeric] extends ContainableImpl[T] with ContainableNumeric[T] {
override def compare(x: T, y: T): Int = implicitly[Numeric[T]].compare(x, y)
}
private class ContainableComparableImpl[T <: Comparable[T]] extends ContainableImpl[T] with ContainableComparable[T] {
override def compare(x: T, y: T): Int = x.compareTo(y)
}
implicit val containableInt: ContainableNumeric[Int] = new ContainableNumericImpl[Int]
implicit val containableBd: ContainableNumeric[BigDecimal] = new ContainableNumericImpl[BigDecimal]
implicit val containableString: ContainableComparable[String] = new ContainableComparableImpl[String]
implicit val containableBool: Containable[Boolean] = new ContainableImpl[Boolean]
}
sealed case class Container[T: Containable](value: T)
sealed case class ContainerSet[T: Containable](value: Set[T])
sealed class ContainerSet2[T: Containable](value: Set[Container[T]])
object ContainerSet2 {
def apply[T: Containable](set: Set[T]): ContainerSet2[T] = {
new ContainerSet2(set.map(el => implicitly[Containable[T]].wrap(el)))
}
}
下面是一个使用示例:
def test(): Unit = {
val ci = Container(1)
val cs = Container("abc")
// val cd = Container(1.0)// fails with a compilation error
val csi = ContainerSet(Set(1))
val cs2i = ContainerSet2(Set(1))
// val csd = ContainerSet(Set(1.0))// fails with a compilation error
// val cs2d = ContainerSet2(Set(1.0))// fails with a compilation error
}
ContainerSet
,我提供了两种不同的实现:一种是包装整个
Set
这段代码可能不是您真正想要的,但是如果没有使用示例,很难猜测,而且这可能是朝着正确方向迈出的一步。