隐式对象的组合爆炸
Combinatorial explosion of implicit objects
我有一个案例class,像这样:
case class Container[T, M](value: T, modifier: M)
我想让那些 T
也有 Ordering
的人在 Container
上有一个 Ordering
。我不想制作 T <: Ordered[T]
,因为 Container
也应该能够包含不可订购的值。
我的第一个尝试是实现 Ordered
,像这样:
case class Container[T, M](value: T, modifier: M) extends Ordered[Container[T, M]] {
override def compare(that: Container[T, M])(implicit ev: Ordering[T]): Int = ev.compare(value, that.value)
}
但这显然不起作用:由于 implicit
参数,compare
不再实现该特征。
于是我决定尝试一种 class 方法:
class ContainerOrdering[T, M](implicit ev: Ordering[T]) extends Ordering[Container[T, M]] {
override def compare(x: Container[T, M], y: Container[T, M]): Int = ev.compare(x.value, y.value)
}
implicit object ContainerOrderingInt extends ContainerOrdering[Int, Int]
这可行(如果我也 import Ordering.Implicits._
),但现在我遇到了一个新问题:对于每个类型 M
,我需要一个单独的隐式对象。现在我想在 M
位置使用的类型不多了(事实上,它们都派生自我在其他地方定义的密封特征),但这仍然意味着我隐式对象的组合爆炸需要定义。我同意每个 T
都有一个单独的隐式对象,但 M
确实应该与此正交。
一定有更好的方法来做到这一点。也许我可以利用 M
扩展密封特征这一事实。但是,我一直无法这样做。有什么建议吗?
将 Ordering
放入伴生对象中!
object Container {
implicit def ordering[T: Ordering, M] = new Ordering[Container[T, M]] {
override def compare(x: Container[T, M], y: Container[T, M]): Int =
implicitly[Ordering[T]].compare(x.value, y.value)
}
}
现在您可以在需要的地方使用 import Container._
进行排序。
(PS:真正的诀窍当然是使排序隐式化,使您不必为每种可能的类型定义每一个单独的排序。)
我有一个案例class,像这样:
case class Container[T, M](value: T, modifier: M)
我想让那些 T
也有 Ordering
的人在 Container
上有一个 Ordering
。我不想制作 T <: Ordered[T]
,因为 Container
也应该能够包含不可订购的值。
我的第一个尝试是实现 Ordered
,像这样:
case class Container[T, M](value: T, modifier: M) extends Ordered[Container[T, M]] {
override def compare(that: Container[T, M])(implicit ev: Ordering[T]): Int = ev.compare(value, that.value)
}
但这显然不起作用:由于 implicit
参数,compare
不再实现该特征。
于是我决定尝试一种 class 方法:
class ContainerOrdering[T, M](implicit ev: Ordering[T]) extends Ordering[Container[T, M]] {
override def compare(x: Container[T, M], y: Container[T, M]): Int = ev.compare(x.value, y.value)
}
implicit object ContainerOrderingInt extends ContainerOrdering[Int, Int]
这可行(如果我也 import Ordering.Implicits._
),但现在我遇到了一个新问题:对于每个类型 M
,我需要一个单独的隐式对象。现在我想在 M
位置使用的类型不多了(事实上,它们都派生自我在其他地方定义的密封特征),但这仍然意味着我隐式对象的组合爆炸需要定义。我同意每个 T
都有一个单独的隐式对象,但 M
确实应该与此正交。
一定有更好的方法来做到这一点。也许我可以利用 M
扩展密封特征这一事实。但是,我一直无法这样做。有什么建议吗?
将 Ordering
放入伴生对象中!
object Container {
implicit def ordering[T: Ordering, M] = new Ordering[Container[T, M]] {
override def compare(x: Container[T, M], y: Container[T, M]): Int =
implicitly[Ordering[T]].compare(x.value, y.value)
}
}
现在您可以在需要的地方使用 import Container._
进行排序。
(PS:真正的诀窍当然是使排序隐式化,使您不必为每种可能的类型定义每一个单独的排序。)