隐式对象的组合爆炸

时间:2015-07-27 11:36:57

标签: scala typeclass

我有一个案例类,如下:

case class Container[T, M](value: T, modifier: M)

我希望OrderingContainer T 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 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确实应该与此正交。

必须有更好的方法来做到这一点。也许我可以利用$window.open延伸密封特性这一事实。但是,我还没有能够这样做。有什么建议吗?

1 个答案:

答案 0 :(得分:3)

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:真正的诀窍当然是使隐含的排序使你无法为每种可能的类型定义每一个排序。)